dav_server_opendalfs/
fs.rs1use dav_server::davpath::DavPath;
19use dav_server::fs::DavMetaData;
20use dav_server::fs::FsError;
21use dav_server::fs::{DavDirEntry, FsFuture};
22use dav_server::fs::{DavFile, FsStream};
23use dav_server::fs::{DavFileSystem, ReadDirMeta};
24use futures::FutureExt;
25use futures::StreamExt;
26use opendal::Operator;
27use std::path::Path;
28
29use super::dir::OpendalStream;
30use super::file::OpendalFile;
31use super::metadata::OpendalMetaData;
32use super::utils::convert_error;
33
34#[derive(Clone)]
60pub struct OpendalFs {
61 pub op: Operator,
62}
63
64impl OpendalFs {
65 pub fn new(op: Operator) -> Box<OpendalFs> {
67 Box::new(OpendalFs { op })
68 }
69
70 fn fs_path(&self, path: &DavPath) -> Result<String, FsError> {
71 String::from_utf8(path.as_bytes().to_vec()).map_err(|_| FsError::GeneralFailure)
72 }
73}
74
75impl DavFileSystem for OpendalFs {
76 fn open<'a>(
77 &'a self,
78 path: &'a DavPath,
79 options: dav_server::fs::OpenOptions,
80 ) -> FsFuture<'a, Box<dyn DavFile>> {
81 async move {
82 let path = self.fs_path(path)?;
83 let file = OpendalFile::open(self.op.clone(), path, options).await?;
84 Ok(Box::new(file) as Box<dyn DavFile>)
85 }
86 .boxed()
87 }
88
89 fn read_dir<'a>(
90 &'a self,
91 path: &'a DavPath,
92 _meta: ReadDirMeta,
93 ) -> FsFuture<'a, FsStream<Box<dyn DavDirEntry>>> {
94 async move {
95 let path = self.fs_path(path)?;
96 self.op
97 .lister(path.as_str())
98 .await
99 .map(|lister| OpendalStream::new(self.op.clone(), lister, path.as_str()).boxed())
100 .map_err(convert_error)
101 }
102 .boxed()
103 }
104
105 fn metadata<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, Box<dyn DavMetaData>> {
106 async move {
107 let path = self.fs_path(path)?;
108 let opendal_metadata = self.op.stat(path.as_str()).await;
109 match opendal_metadata {
110 Ok(metadata) => {
111 let webdav_metadata = OpendalMetaData::new(metadata);
112 Ok(Box::new(webdav_metadata) as Box<dyn DavMetaData>)
113 }
114 Err(e) => Err(convert_error(e)),
115 }
116 }
117 .boxed()
118 }
119
120 fn create_dir<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
121 async move {
122 let path = self.fs_path(path)?;
123
124 let parent = Path::new(&path).parent().unwrap();
128 match self.op.exists(parent.to_str().unwrap()).await {
129 Ok(exist) => {
130 if !exist && parent != Path::new("/") {
131 return Err(FsError::NotFound);
132 }
133 }
134 Err(e) => {
135 return Err(convert_error(e));
136 }
137 }
138
139 let path = path.as_str();
140 let exist = self.op.exists(path).await;
142 match exist {
143 Ok(exist) => match exist {
144 true => Err(FsError::Exists),
145 false => {
146 let res = self.op.create_dir(path).await;
147 match res {
148 Ok(_) => Ok(()),
149 Err(e) => Err(convert_error(e)),
150 }
151 }
152 },
153 Err(e) => Err(convert_error(e)),
154 }
155 }
156 .boxed()
157 }
158
159 fn remove_dir<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
160 self.remove_file(path)
161 }
162
163 fn remove_file<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
164 async move {
165 let path = self.fs_path(path)?;
166 self.op.delete(&path).await.map_err(convert_error)
167 }
168 .boxed()
169 }
170
171 fn rename<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
172 async move {
173 let from_path = from
174 .as_rel_ospath()
175 .to_str()
176 .ok_or(FsError::GeneralFailure)?;
177 let to_path = to.as_rel_ospath().to_str().ok_or(FsError::GeneralFailure)?;
178 if from.is_collection() {
179 let _ = self.remove_file(to).await;
180 }
181 self.op
182 .rename(from_path, to_path)
183 .await
184 .map_err(convert_error)
185 }
186 .boxed()
187 }
188
189 fn copy<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
190 async move {
191 let from_path = from
192 .as_rel_ospath()
193 .to_str()
194 .ok_or(FsError::GeneralFailure)?;
195 let to_path = to.as_rel_ospath().to_str().ok_or(FsError::GeneralFailure)?;
196 self.op
197 .copy(from_path, to_path)
198 .await
199 .map_err(convert_error)
200 }
201 .boxed()
202 }
203}