1use std::fmt::Debug;
19use std::fmt::Formatter;
20use std::sync::Arc;
21
22use crate::raw::oio::FlatLister;
23use crate::raw::oio::List;
24use crate::raw::oio::PrefixLister;
25use crate::raw::*;
26use crate::*;
27
28#[derive(Debug, Clone)]
30pub struct SimulateLayer {
31 list_recursive: bool,
32 stat_dir: bool,
33 create_dir: bool,
34 delete_recursive: bool,
35}
36
37impl Default for SimulateLayer {
38 fn default() -> Self {
39 Self {
40 list_recursive: true,
41 stat_dir: true,
42 create_dir: true,
43 delete_recursive: true,
44 }
45 }
46}
47
48impl SimulateLayer {
49 pub fn with_list_recursive(mut self, enabled: bool) -> Self {
51 self.list_recursive = enabled;
52 self
53 }
54
55 pub fn with_stat_dir(mut self, enabled: bool) -> Self {
57 self.stat_dir = enabled;
58 self
59 }
60
61 pub fn with_create_dir(mut self, enabled: bool) -> Self {
63 self.create_dir = enabled;
64 self
65 }
66
67 pub fn with_delete_recursive(mut self, enabled: bool) -> Self {
69 self.delete_recursive = enabled;
70 self
71 }
72}
73
74impl<A: Access> Layer<A> for SimulateLayer {
75 type LayeredAccess = SimulateAccessor<A>;
76
77 fn layer(&self, inner: A) -> Self::LayeredAccess {
78 let info = inner.info();
79 info.update_full_capability(|mut cap| {
80 if self.create_dir && cap.list && cap.write_can_empty {
81 cap.create_dir = true;
82 }
83 if self.delete_recursive && cap.list && cap.delete {
84 cap.delete_with_recursive = true;
85 }
86 cap
87 });
88
89 SimulateAccessor {
90 config: self.clone(),
91 info,
92 inner: Arc::new(inner),
93 }
94 }
95}
96
97pub struct SimulateAccessor<A: Access> {
99 config: SimulateLayer,
100 info: Arc<AccessorInfo>,
101 inner: Arc<A>,
102}
103
104impl<A: Access> Debug for SimulateAccessor<A> {
105 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
106 self.inner.fmt(f)
107 }
108}
109
110impl<A: Access> SimulateAccessor<A> {
111 async fn simulate_create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
112 let capability = self.info.native_capability();
113
114 if capability.create_dir || !self.config.create_dir {
115 return self.inner().create_dir(path, args).await;
116 }
117
118 if capability.write_can_empty && capability.list {
119 let (_, mut w) = self.inner.write(path, OpWrite::default()).await?;
120 oio::Write::close(&mut w).await?;
121 return Ok(RpCreateDir::default());
122 }
123
124 self.inner.create_dir(path, args).await
125 }
126
127 async fn simulate_stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
128 let capability = self.info.native_capability();
129
130 if path == "/" {
131 return Ok(RpStat::new(Metadata::new(EntryMode::DIR)));
132 }
133
134 if path.ends_with('/') {
135 if capability.create_dir {
136 let meta = self.inner.stat(path, args.clone()).await?.into_metadata();
137
138 if meta.is_file() {
139 return Err(Error::new(
140 ErrorKind::NotFound,
141 "stat expected a directory, but found a file",
142 ));
143 }
144
145 return Ok(RpStat::new(meta));
146 }
147
148 if self.config.stat_dir && capability.list_with_recursive {
149 let (_, mut l) = self
150 .inner
151 .list(path, OpList::default().with_recursive(true).with_limit(1))
152 .await?;
153
154 return if oio::List::next(&mut l).await?.is_some() {
155 Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
156 } else {
157 Err(Error::new(
158 ErrorKind::NotFound,
159 "the directory is not found",
160 ))
161 };
162 }
163 }
164
165 self.inner.stat(path, args).await
166 }
167
168 async fn simulate_list(
169 &self,
170 path: &str,
171 args: OpList,
172 ) -> Result<(RpList, SimulateLister<A, A::Lister>)> {
173 let cap = self.info.native_capability();
174
175 let recursive = args.recursive();
176 let forward = args;
177
178 let (rp, lister) = match (
179 recursive,
180 cap.list_with_recursive,
181 self.config.list_recursive,
182 ) {
183 (_, true, _) => {
185 let (rp, p) = self.inner.list(path, forward).await?;
186 (rp, SimulateLister::One(p))
187 }
188 (true, false, true) => {
190 if path.ends_with('/') {
191 let p = FlatLister::new(self.inner.clone(), path);
192 (RpList::default(), SimulateLister::Two(p))
193 } else {
194 let parent = get_parent(path);
195 let p = FlatLister::new(self.inner.clone(), parent);
196 let p = PrefixLister::new(p, path);
197 (RpList::default(), SimulateLister::Four(p))
198 }
199 }
200 (true, false, false) => {
202 let (rp, p) = self.inner.list(path, forward).await?;
203 (rp, SimulateLister::One(p))
204 }
205 (false, false, _) => {
207 if path.ends_with('/') {
208 let (rp, p) = self.inner.list(path, forward).await?;
209 (rp, SimulateLister::One(p))
210 } else {
211 let parent = get_parent(path);
212 let (rp, p) = self.inner.list(parent, forward).await?;
213 let p = PrefixLister::new(p, path);
214 (rp, SimulateLister::Three(p))
215 }
216 }
217 };
218
219 Ok((rp, lister))
220 }
221
222 pub(crate) async fn simulate_delete_with_recursive<D: oio::Delete>(
223 &self,
224 deleter: &mut D,
225 path: &str,
226 args: OpDelete,
227 ) -> Result<()> {
228 if !self.info.full_capability().delete_with_recursive {
229 return Err(Error::new(
230 ErrorKind::Unsupported,
231 "recursive delete is not supported",
232 ));
233 }
234
235 let non_recursive = args.clone().with_recursive(false);
236
237 let (_rp, mut lister) = self
238 .simulate_list(path, OpList::new().with_recursive(true))
239 .await?;
240
241 while let Some(entry) = lister.next().await? {
242 let entry = entry.into_entry();
243 let mut entry_args = non_recursive.clone();
244 if let Some(version) = entry.metadata().version() {
245 entry_args = entry_args.with_version(version);
246 }
247 deleter.delete(entry.path(), entry_args).await?;
248 }
249
250 Ok(())
251 }
252}
253
254impl<A: Access> LayeredAccess for SimulateAccessor<A> {
255 type Inner = A;
256 type Reader = A::Reader;
257 type Writer = A::Writer;
258 type Lister = SimulateLister<A, A::Lister>;
259 type Deleter = SimulateDeleter<A, A::Deleter>;
260
261 fn inner(&self) -> &Self::Inner {
262 &self.inner
263 }
264
265 fn info(&self) -> Arc<AccessorInfo> {
266 self.info.clone()
267 }
268
269 async fn create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
270 self.simulate_create_dir(path, args).await
271 }
272
273 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
274 self.inner.read(path, args).await
275 }
276
277 async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::Writer)> {
278 self.inner.write(path, args).await
279 }
280
281 async fn stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
282 self.simulate_stat(path, args).await
283 }
284
285 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
286 let (rp, deleter) = self.inner().delete().await?;
287 let accessor = SimulateAccessor {
288 config: self.config.clone(),
289 info: self.info.clone(),
290 inner: self.inner.clone(),
291 };
292
293 Ok((rp, SimulateDeleter::new(accessor, deleter)))
294 }
295
296 async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> {
297 self.simulate_list(path, args).await
298 }
299
300 async fn presign(&self, path: &str, args: OpPresign) -> Result<RpPresign> {
301 self.inner.presign(path, args).await
302 }
303}
304
305pub type SimulateLister<A, P> =
306 FourWays<P, FlatLister<Arc<A>, P>, PrefixLister<P>, PrefixLister<FlatLister<Arc<A>, P>>>;
307
308pub struct SimulateDeleter<A: Access, D> {
310 accessor: SimulateAccessor<A>,
311 deleter: D,
312}
313
314impl<A: Access, D> SimulateDeleter<A, D> {
315 pub fn new(accessor: SimulateAccessor<A>, deleter: D) -> Self {
316 Self { accessor, deleter }
317 }
318}
319
320impl<A: Access, D: oio::Delete> oio::Delete for SimulateDeleter<A, D> {
321 async fn delete(&mut self, path: &str, args: OpDelete) -> Result<()> {
322 if args.recursive() {
323 let cap = self.accessor.info.native_capability();
324
325 if cap.delete_with_recursive {
326 return self.deleter.delete(path, args).await;
327 }
328
329 if self.accessor.config.delete_recursive {
330 return self
331 .accessor
332 .simulate_delete_with_recursive(&mut self.deleter, path, args)
333 .await;
334 }
335 }
336
337 self.deleter.delete(path, args).await
338 }
339
340 fn close(&mut self) -> impl Future<Output = Result<()>> + MaybeSend {
341 self.deleter.close()
342 }
343}