1 | use std::{io::Error as IoError, path::PathBuf, pin::Pin}; |
2 | |
3 | use bytes::Bytes; |
4 | use futures::{Stream, stream::BoxStream}; |
5 | |
6 | use crate::{ |
7 | address::Addressable, |
8 | storage_fs::FileSystem, |
9 | }; |
10 | |
11 | #[derive(thiserror::Error, Debug)] |
12 | pub enum Error { |
13 | #[error("Unspecified Storage Error")] |
14 | Unspecified, |
15 | #[error("Storage IO: {0}")] |
16 | Io(#[from] IoError), |
17 | #[error("Object Not Found")] |
18 | NotFound, |
19 | } |
20 | |
21 | pub struct InnerStream { |
22 | stream: BoxStream<'static, Result<Bytes, std::io::Error>>, |
23 | } |
24 | |
25 | impl InnerStream { |
26 | pub fn new(stream: BoxStream<'static, Result<Bytes, std::io::Error>>) -> Self { |
27 | InnerStream { stream } |
28 | } |
29 | } |
30 | |
31 | impl Stream for InnerStream { |
32 | type Item = Result<Bytes, std::io::Error>; |
33 | |
34 | fn poll_next( |
35 | self: Pin<&mut Self>, |
36 | cx: &mut std::task::Context<'_>, |
37 | ) -> std::task::Poll<Option<Self::Item>> { |
38 | Pin::new(&mut self.get_mut().stream).poll_next(cx) |
39 | } |
40 | } |
41 | |
42 | /// The storage trait needs to be implemented for accessing objects from the |
43 | /// platform. This API is based on registry/storage/driver/storagedriver.go in |
44 | /// the distribution codebase. |
45 | pub trait StorageIface: Sync + Send { |
46 | /// List a single directory of objects |
47 | // async fn list(&self, addr: &Address) -> Result<Vec<Object>, Error>; |
48 | // async fn stat(&self, addr: &Address) -> Result<Option<Object>, Error>; |
49 | // async fn read_bytes(&self, addr: &Address) -> Result<Option<Vec<u8>>, Error>; |
50 | /// Check if an object exists at the given address |
51 | fn exists<A>(&self, path: &A) -> impl Future<Output = Result<bool, Error>> + Send |
52 | where |
53 | A: Addressable + Send + Sync; |
54 | /// Write bytes to the address, truncating any existing object |
55 | fn write_all<A>( |
56 | &self, |
57 | path: &A, |
58 | bytes: &[u8], |
59 | ) -> impl Future<Output = Result<(), Error>> + Send |
60 | where |
61 | A: Addressable + Send + Sync; |
62 | |
63 | /// write bytes to a file that has already been created |
64 | fn write<A>(&self, path: &A, bytes: &[u8]) -> impl Future<Output = Result<(), Error>> + Send |
65 | where |
66 | A: Addressable + Send + Sync; |
67 | |
68 | fn mv<A, B>(&self, src: &A, dst: &B) -> impl Future<Output = Result<(), Error>> + Send |
69 | where |
70 | A: Addressable + Send + Sync, |
71 | B: Addressable + Send + Sync; |
72 | // fn mv (&self, )std::future::Future<Output = ()> + Send |
73 | fn read<A>(&self, src: &A) -> impl Future<Output = Result<InnerStream, Error>> + Send |
74 | where |
75 | A: Addressable + Send + Sync; |
76 | |
77 | fn read_bytes<A>(&self, src: &A) -> impl Future<Output = Result<Bytes, Error>> + Send |
78 | where |
79 | A: Addressable + Send + Sync; |
80 | |
81 | fn delete<A>(&self, src: &A) -> impl Future<Output = Result<(), Error>> + Send |
82 | where |
83 | A: Addressable + Send + Sync; |
84 | } |
85 | |
86 | #[derive(Debug, Clone)] |
87 | pub enum Storage { |
88 | FileSystem { base: PathBuf }, |
89 | } |
90 | |
91 | impl Storage { |
92 | pub fn init(&self) -> Result<(), Error> { |
93 | match self { |
94 | Storage::FileSystem { base } => FileSystem { base: base.clone() }.init(), |
95 | } |
96 | } |
97 | |
98 | pub fn inner(&self) -> impl StorageIface { |
99 | match self { |
100 | Storage::FileSystem { base } => FileSystem { base: base.clone() }, |
101 | } |
102 | } |
103 | } |