1use std::fmt::Debug;
16use std::sync::Arc;
17
18use derive_builder::Builder;
19pub use oio::*;
20pub use opendal::raw::{
21 Layer, OpCopy, OpDelete, OpList, OpRead, OpWrite, RpRead, Service, Servicer, oio,
22};
23pub use opendal::{Buffer, BytesRange, Error, ErrorKind, Metadata, OperationContext, Result};
24
25pub type MockWriterFactory = Arc<dyn Fn(&str, OpWrite, oio::Writer) -> oio::Writer + Send + Sync>;
26pub type MockReaderFactory = Arc<dyn Fn(&str, OpRead, oio::Reader) -> oio::Reader + Send + Sync>;
27pub type MockListerFactory = Arc<dyn Fn(&str, OpList, oio::Lister) -> oio::Lister + Send + Sync>;
28pub type MockDeleterFactory = Arc<dyn Fn(oio::Deleter) -> oio::Deleter + Send + Sync>;
29pub type CopyInterceptor = Arc<dyn Fn(&str, &str, OpCopy) -> Option<Result<()>> + Send + Sync>;
30
31#[derive(Builder)]
32pub struct MockLayer {
33 #[builder(setter(strip_option), default)]
34 writer_factory: Option<MockWriterFactory>,
35 #[builder(setter(strip_option), default)]
36 reader_factory: Option<MockReaderFactory>,
37 #[builder(setter(strip_option), default)]
38 lister_factory: Option<MockListerFactory>,
39 #[builder(setter(strip_option), default)]
40 deleter_factory: Option<MockDeleterFactory>,
41 #[builder(setter(strip_option), default)]
42 copy_interceptor: Option<CopyInterceptor>,
43}
44
45impl Clone for MockLayer {
46 fn clone(&self) -> Self {
47 Self {
48 writer_factory: self.writer_factory.clone(),
49 reader_factory: self.reader_factory.clone(),
50 lister_factory: self.lister_factory.clone(),
51 deleter_factory: self.deleter_factory.clone(),
52 copy_interceptor: self.copy_interceptor.clone(),
53 }
54 }
55}
56
57impl Debug for MockLayer {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 f.debug_struct("MockLayer").finish_non_exhaustive()
60 }
61}
62
63impl Layer for MockLayer {
64 fn apply_service(&self, inner: Servicer) -> Servicer {
65 Arc::new(MockService {
66 inner,
67 writer_factory: self.writer_factory.clone(),
68 reader_factory: self.reader_factory.clone(),
69 lister_factory: self.lister_factory.clone(),
70 deleter_factory: self.deleter_factory.clone(),
71 copy_interceptor: self.copy_interceptor.clone(),
72 })
73 }
74}
75
76struct MockService {
77 inner: Servicer,
78 writer_factory: Option<MockWriterFactory>,
79 reader_factory: Option<MockReaderFactory>,
80 lister_factory: Option<MockListerFactory>,
81 deleter_factory: Option<MockDeleterFactory>,
82 copy_interceptor: Option<CopyInterceptor>,
83}
84
85impl Debug for MockService {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 f.debug_struct("MockService")
88 .field("inner", &self.inner)
89 .finish_non_exhaustive()
90 }
91}
92
93impl Service for MockService {
94 type Reader = oio::Reader;
95 type Writer = oio::Writer;
96 type Lister = oio::Lister;
97 type Deleter = oio::Deleter;
98 type Copier = oio::Copier;
99
100 fn info(&self) -> opendal::raw::ServiceInfo {
101 self.inner.info()
102 }
103
104 fn capability(&self) -> opendal::Capability {
105 self.inner.capability()
106 }
107
108 async fn create_dir(
109 &self,
110 ctx: &OperationContext,
111 path: &str,
112 args: opendal::raw::OpCreateDir,
113 ) -> Result<opendal::raw::RpCreateDir> {
114 self.inner.create_dir(ctx, path, args).await
115 }
116
117 async fn stat(
118 &self,
119 ctx: &OperationContext,
120 path: &str,
121 args: opendal::raw::OpStat,
122 ) -> Result<opendal::raw::RpStat> {
123 self.inner.stat(ctx, path, args).await
124 }
125
126 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
127 let reader = self.inner.read(ctx, path, args.clone())?;
128 if let Some(reader_factory) = self.reader_factory.as_ref() {
129 Ok(reader_factory(path, args, reader))
130 } else {
131 Ok(reader)
132 }
133 }
134
135 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
136 let writer = self.inner.write(ctx, path, args.clone())?;
137 if let Some(writer_factory) = self.writer_factory.as_ref() {
138 Ok(writer_factory(path, args, writer))
139 } else {
140 Ok(writer)
141 }
142 }
143
144 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter> {
145 let deleter = self.inner.delete(ctx)?;
146 if let Some(deleter_factory) = self.deleter_factory.as_ref() {
147 Ok(deleter_factory(deleter))
148 } else {
149 Ok(deleter)
150 }
151 }
152
153 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
154 let lister = self.inner.list(ctx, path, args.clone())?;
155 if let Some(lister_factory) = self.lister_factory.as_ref() {
156 Ok(lister_factory(path, args, lister))
157 } else {
158 Ok(lister)
159 }
160 }
161
162 fn copy(
163 &self,
164 ctx: &OperationContext,
165 from: &str,
166 to: &str,
167 args: OpCopy,
168 opts: opendal::raw::OpCopier,
169 ) -> Result<Self::Copier> {
170 if let Some(result) = self
171 .copy_interceptor
172 .as_ref()
173 .and_then(|copy_interceptor| copy_interceptor(from, to, args.clone()))
174 {
175 result?;
176 return Ok(Box::new(oio::OneShotCopier::completed()) as oio::Copier);
177 }
178
179 self.inner.copy(ctx, from, to, args, opts)
180 }
181
182 async fn rename(
183 &self,
184 ctx: &OperationContext,
185 from: &str,
186 to: &str,
187 args: opendal::raw::OpRename,
188 ) -> Result<opendal::raw::RpRename> {
189 self.inner.rename(ctx, from, to, args).await
190 }
191
192 async fn presign(
193 &self,
194 ctx: &OperationContext,
195 path: &str,
196 args: opendal::raw::OpPresign,
197 ) -> Result<opendal::raw::RpPresign> {
198 self.inner.presign(ctx, path, args).await
199 }
200}
201
202pub struct MockReader {
203 inner: oio::Reader,
204}
205
206impl oio::Read for MockReader {
207 async fn open(
208 &self,
209 range: opendal::BytesRange,
210 ) -> Result<(opendal::raw::RpRead, Box<dyn oio::ReadStreamDyn>)> {
211 self.inner.open(range).await
212 }
213
214 async fn read(&self, range: opendal::BytesRange) -> Result<(opendal::raw::RpRead, Buffer)> {
215 self.inner.read(range).await
216 }
217}
218
219pub struct MockWriter {
220 inner: oio::Writer,
221}
222
223impl oio::Write for MockWriter {
224 async fn write(&mut self, bs: Buffer) -> Result<()> {
225 self.inner.write(bs).await
226 }
227
228 async fn close(&mut self) -> Result<Metadata> {
229 self.inner.close().await
230 }
231
232 async fn abort(&mut self) -> Result<()> {
233 self.inner.abort().await
234 }
235}
236
237pub struct MockLister {
238 inner: oio::Lister,
239}
240
241impl oio::List for MockLister {
242 async fn next(&mut self) -> Result<Option<oio::Entry>> {
243 self.inner.next().await
244 }
245}
246
247pub struct MockDeleter {
248 inner: oio::Deleter,
249}
250
251impl oio::Delete for MockDeleter {
252 async fn delete(&mut self, path: &str, args: OpDelete) -> Result<()> {
253 self.inner.delete(path, args).await
254 }
255
256 async fn close(&mut self) -> Result<()> {
257 self.inner.close().await
258 }
259}