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
129 .op
130 .exists(format!("{}/", parent.display()).as_str())
131 .await
132 {
133 Ok(exist) => {
134 if !exist && parent != Path::new("/") {
135 return Err(FsError::NotFound);
136 }
137 }
138 Err(e) => {
139 return Err(convert_error(e));
140 }
141 }
142
143 let path = path.as_str();
144 let exist = self.op.exists(path).await;
146 match exist {
147 Ok(exist) => match exist {
148 true => Err(FsError::Exists),
149 false => {
150 let res = self.op.create_dir(path).await;
151 match res {
152 Ok(_) => Ok(()),
153 Err(e) => Err(convert_error(e)),
154 }
155 }
156 },
157 Err(e) => Err(convert_error(e)),
158 }
159 }
160 .boxed()
161 }
162
163 fn remove_dir<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
164 self.remove_file(path)
165 }
166
167 fn remove_file<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
168 async move {
169 let path = self.fs_path(path)?;
170 self.op.delete(&path).await.map_err(convert_error)
171 }
172 .boxed()
173 }
174
175 fn rename<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
176 async move {
177 let from_path = from
178 .as_rel_ospath()
179 .to_str()
180 .ok_or(FsError::GeneralFailure)?;
181 let to_path = to.as_rel_ospath().to_str().ok_or(FsError::GeneralFailure)?;
182 if from.is_collection() {
183 let _ = self.remove_file(to).await;
184 }
185 self.op
186 .rename(from_path, to_path)
187 .await
188 .map_err(convert_error)
189 }
190 .boxed()
191 }
192
193 fn copy<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
194 async move {
195 let from_path = from
196 .as_rel_ospath()
197 .to_str()
198 .ok_or(FsError::GeneralFailure)?;
199 let to_path = to.as_rel_ospath().to_str().ok_or(FsError::GeneralFailure)?;
200 self.op
201 .copy(from_path, to_path)
202 .await
203 .map_err(convert_error)
204 }
205 .boxed()
206 }
207}