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 type Composer = oio::Composer;
100
101 fn info(&self) -> opendal::raw::ServiceInfo {
102 self.inner.info()
103 }
104
105 fn capability(&self) -> opendal::Capability {
106 self.inner.capability()
107 }
108
109 async fn create_dir(
110 &self,
111 ctx: &OperationContext,
112 path: &str,
113 args: opendal::raw::OpCreateDir,
114 ) -> Result<opendal::raw::RpCreateDir> {
115 self.inner.create_dir(ctx, path, args).await
116 }
117
118 async fn stat(
119 &self,
120 ctx: &OperationContext,
121 path: &str,
122 args: opendal::raw::OpStat,
123 ) -> Result<opendal::raw::RpStat> {
124 self.inner.stat(ctx, path, args).await
125 }
126
127 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
128 let reader = self.inner.read(ctx, path, args.clone())?;
129 if let Some(reader_factory) = self.reader_factory.as_ref() {
130 Ok(reader_factory(path, args, reader))
131 } else {
132 Ok(reader)
133 }
134 }
135
136 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
137 let writer = self.inner.write(ctx, path, args.clone())?;
138 if let Some(writer_factory) = self.writer_factory.as_ref() {
139 Ok(writer_factory(path, args, writer))
140 } else {
141 Ok(writer)
142 }
143 }
144
145 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter> {
146 let deleter = self.inner.delete(ctx)?;
147 if let Some(deleter_factory) = self.deleter_factory.as_ref() {
148 Ok(deleter_factory(deleter))
149 } else {
150 Ok(deleter)
151 }
152 }
153
154 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
155 let lister = self.inner.list(ctx, path, args.clone())?;
156 if let Some(lister_factory) = self.lister_factory.as_ref() {
157 Ok(lister_factory(path, args, lister))
158 } else {
159 Ok(lister)
160 }
161 }
162
163 fn copy(
164 &self,
165 ctx: &OperationContext,
166 from: &str,
167 to: &str,
168 args: OpCopy,
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)
180 }
181
182 fn compose(
183 &self,
184 ctx: &OperationContext,
185 to: &str,
186 args: opendal::raw::OpCompose,
187 ) -> Result<Self::Composer> {
188 self.inner.compose(ctx, to, args)
189 }
190
191 async fn rename(
192 &self,
193 ctx: &OperationContext,
194 from: &str,
195 to: &str,
196 args: opendal::raw::OpRename,
197 ) -> Result<opendal::raw::RpRename> {
198 self.inner.rename(ctx, from, to, args).await
199 }
200
201 async fn presign(
202 &self,
203 ctx: &OperationContext,
204 path: &str,
205 args: opendal::raw::OpPresign,
206 ) -> Result<opendal::raw::RpPresign> {
207 self.inner.presign(ctx, path, args).await
208 }
209}
210
211pub struct MockReader {
212 inner: oio::Reader,
213}
214
215impl oio::Read for MockReader {
216 async fn open(
217 &self,
218 range: opendal::BytesRange,
219 ) -> Result<(opendal::raw::RpRead, Box<dyn oio::ReadStreamDyn>)> {
220 self.inner.open(range).await
221 }
222
223 async fn read(&self, range: opendal::BytesRange) -> Result<(opendal::raw::RpRead, Buffer)> {
224 self.inner.read(range).await
225 }
226}
227
228pub struct MockWriter {
229 inner: oio::Writer,
230}
231
232impl oio::Write for MockWriter {
233 async fn write(&mut self, bs: Buffer) -> Result<()> {
234 self.inner.write(bs).await
235 }
236
237 async fn close(&mut self) -> Result<Metadata> {
238 self.inner.close().await
239 }
240
241 async fn abort(&mut self) -> Result<()> {
242 self.inner.abort().await
243 }
244}
245
246pub struct MockLister {
247 inner: oio::Lister,
248}
249
250impl oio::List for MockLister {
251 async fn next(&mut self) -> Result<Option<oio::Entry>> {
252 self.inner.next().await
253 }
254}
255
256pub struct MockDeleter {
257 inner: oio::Deleter,
258}
259
260impl oio::Delete for MockDeleter {
261 async fn delete(&mut self, path: &str, args: OpDelete) -> Result<()> {
262 self.inner.delete(path, args).await
263 }
264
265 async fn close(&mut self) -> Result<()> {
266 self.inner.close().await
267 }
268}