1use std::fmt::Debug;
19use std::fmt::Formatter;
20use std::sync::Arc;
21
22use crate::raw::oio::FlatLister;
23use crate::raw::oio::PrefixLister;
24use crate::raw::*;
25use crate::*;
26
27#[derive(Debug, Clone)]
29pub struct SimulateLayer {
30 list_recursive: bool,
31 stat_dir: bool,
32 create_dir: bool,
33}
34
35impl Default for SimulateLayer {
36 fn default() -> Self {
37 Self {
38 list_recursive: true,
39 stat_dir: true,
40 create_dir: true,
41 }
42 }
43}
44
45impl SimulateLayer {
46 pub fn with_list_recursive(mut self, enabled: bool) -> Self {
48 self.list_recursive = enabled;
49 self
50 }
51
52 pub fn with_stat_dir(mut self, enabled: bool) -> Self {
54 self.stat_dir = enabled;
55 self
56 }
57
58 pub fn with_create_dir(mut self, enabled: bool) -> Self {
60 self.create_dir = enabled;
61 self
62 }
63}
64
65impl<A: Access> Layer<A> for SimulateLayer {
66 type LayeredAccess = SimulateAccessor<A>;
67
68 fn layer(&self, inner: A) -> Self::LayeredAccess {
69 let info = inner.info();
70 info.update_full_capability(|mut cap| {
71 if self.create_dir && cap.list && cap.write_can_empty {
72 cap.create_dir = true;
73 }
74 cap
75 });
76
77 SimulateAccessor {
78 config: self.clone(),
79 info,
80 inner: Arc::new(inner),
81 }
82 }
83}
84
85pub struct SimulateAccessor<A: Access> {
87 config: SimulateLayer,
88 info: Arc<AccessorInfo>,
89 inner: Arc<A>,
90}
91
92impl<A: Access> Debug for SimulateAccessor<A> {
93 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
94 self.inner.fmt(f)
95 }
96}
97
98impl<A: Access> SimulateAccessor<A> {
99 async fn simulate_create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
100 let capability = self.info.native_capability();
101
102 if capability.create_dir || !self.config.create_dir {
103 return self.inner().create_dir(path, args).await;
104 }
105
106 if capability.write_can_empty && capability.list {
107 let (_, mut w) = self.inner.write(path, OpWrite::default()).await?;
108 oio::Write::close(&mut w).await?;
109 return Ok(RpCreateDir::default());
110 }
111
112 self.inner.create_dir(path, args).await
113 }
114
115 async fn simulate_stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
116 let capability = self.info.native_capability();
117
118 if path == "/" {
119 return Ok(RpStat::new(Metadata::new(EntryMode::DIR)));
120 }
121
122 if path.ends_with('/') {
123 if capability.create_dir {
124 let meta = self.inner.stat(path, args.clone()).await?.into_metadata();
125
126 if meta.is_file() {
127 return Err(Error::new(
128 ErrorKind::NotFound,
129 "stat expected a directory, but found a file",
130 ));
131 }
132
133 return Ok(RpStat::new(meta));
134 }
135
136 if self.config.stat_dir && capability.list_with_recursive {
137 let (_, mut l) = self
138 .inner
139 .list(path, OpList::default().with_recursive(true).with_limit(1))
140 .await?;
141
142 return if oio::List::next(&mut l).await?.is_some() {
143 Ok(RpStat::new(Metadata::new(EntryMode::DIR)))
144 } else {
145 Err(Error::new(
146 ErrorKind::NotFound,
147 "the directory is not found",
148 ))
149 };
150 }
151 }
152
153 self.inner.stat(path, args).await
154 }
155
156 async fn simulate_list(
157 &self,
158 path: &str,
159 args: OpList,
160 ) -> Result<(RpList, SimulateLister<A, A::Lister>)> {
161 let cap = self.info.native_capability();
162
163 let recursive = args.recursive();
164 let forward = args;
165
166 let (rp, lister) = match (
167 recursive,
168 cap.list_with_recursive,
169 self.config.list_recursive,
170 ) {
171 (_, true, _) => {
173 let (rp, p) = self.inner.list(path, forward).await?;
174 (rp, SimulateLister::One(p))
175 }
176 (true, false, true) => {
178 if path.ends_with('/') {
179 let p = FlatLister::new(self.inner.clone(), path);
180 (RpList::default(), SimulateLister::Two(p))
181 } else {
182 let parent = get_parent(path);
183 let p = FlatLister::new(self.inner.clone(), parent);
184 let p = PrefixLister::new(p, path);
185 (RpList::default(), SimulateLister::Four(p))
186 }
187 }
188 (true, false, false) => {
190 let (rp, p) = self.inner.list(path, forward).await?;
191 (rp, SimulateLister::One(p))
192 }
193 (false, false, _) => {
195 if path.ends_with('/') {
196 let (rp, p) = self.inner.list(path, forward).await?;
197 (rp, SimulateLister::One(p))
198 } else {
199 let parent = get_parent(path);
200 let (rp, p) = self.inner.list(parent, forward).await?;
201 let p = PrefixLister::new(p, path);
202 (rp, SimulateLister::Three(p))
203 }
204 }
205 };
206
207 Ok((rp, lister))
208 }
209}
210
211impl<A: Access> LayeredAccess for SimulateAccessor<A> {
212 type Inner = A;
213 type Reader = A::Reader;
214 type Writer = A::Writer;
215 type Lister = SimulateLister<A, A::Lister>;
216 type Deleter = A::Deleter;
217
218 fn inner(&self) -> &Self::Inner {
219 &self.inner
220 }
221
222 fn info(&self) -> Arc<AccessorInfo> {
223 self.info.clone()
224 }
225
226 async fn create_dir(&self, path: &str, args: OpCreateDir) -> Result<RpCreateDir> {
227 self.simulate_create_dir(path, args).await
228 }
229
230 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
231 self.inner.read(path, args).await
232 }
233
234 async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::Writer)> {
235 self.inner.write(path, args).await
236 }
237
238 async fn stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
239 self.simulate_stat(path, args).await
240 }
241
242 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
243 self.inner().delete().await
244 }
245
246 async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> {
247 self.simulate_list(path, args).await
248 }
249
250 async fn presign(&self, path: &str, args: OpPresign) -> Result<RpPresign> {
251 self.inner.presign(path, args).await
252 }
253}
254
255pub type SimulateLister<A, P> =
256 FourWays<P, FlatLister<Arc<A>, P>, PrefixLister<P>, PrefixLister<FlatLister<Arc<A>, P>>>;