1use std::fmt::Debug;
19use std::future::Future;
20use std::sync::Arc;
21
22use crate::raw::*;
23use crate::*;
24
25#[derive(Clone, PartialEq, Eq, Hash)]
30pub struct ServiceInfo {
31 scheme: &'static str,
32 root: Arc<str>,
33 name: Arc<str>,
34}
35
36impl Debug for ServiceInfo {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.debug_struct("ServiceInfo")
39 .field("scheme", &self.scheme())
40 .field("root", &self.root())
41 .field("name", &self.name())
42 .finish_non_exhaustive()
43 }
44}
45
46impl ServiceInfo {
47 pub fn new(scheme: &'static str, root: impl AsRef<str>, name: impl AsRef<str>) -> Self {
49 Self {
50 scheme,
51 root: Arc::from(root.as_ref()),
52 name: Arc::from(name.as_ref()),
53 }
54 }
55
56 pub fn with_scheme(scheme: &'static str) -> Self {
58 Self::new(scheme, "", "")
59 }
60
61 pub fn with_root(&self, root: impl AsRef<str>) -> Self {
63 Self {
64 scheme: self.scheme,
65 root: Arc::from(root.as_ref()),
66 name: self.name.clone(),
67 }
68 }
69
70 pub fn scheme(&self) -> &'static str {
72 self.scheme
73 }
74
75 pub fn root(&self) -> Arc<str> {
77 self.root.clone()
78 }
79
80 pub fn name(&self) -> Arc<str> {
89 self.name.clone()
90 }
91}
92
93pub trait Service: Send + Sync + Debug + Unpin + 'static {
110 type Reader: oio::Read;
112 type Writer: oio::Write;
114 type Lister: oio::List;
116 type Deleter: oio::Delete;
118 type Copier: oio::Copy;
120 type Composer: oio::Compose;
122
123 fn info(&self) -> ServiceInfo;
125
126 fn capability(&self) -> Capability;
132
133 fn create_dir(
142 &self,
143 ctx: &OperationContext,
144 path: &str,
145 args: OpCreateDir,
146 ) -> impl Future<Output = Result<RpCreateDir>> + MaybeSend;
147
148 fn stat(
158 &self,
159 ctx: &OperationContext,
160 path: &str,
161 args: OpStat,
162 ) -> impl Future<Output = Result<RpStat>> + MaybeSend;
163
164 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader>;
173
174 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer>;
182
183 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter>;
192
193 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister>;
202
203 fn copy(
212 &self,
213 ctx: &OperationContext,
214 from: &str,
215 to: &str,
216 args: OpCopy,
217 ) -> Result<Self::Copier>;
218
219 fn compose(
223 &self,
224 _ctx: &OperationContext,
225 _to: &str,
226 _args: OpCompose,
227 ) -> Result<Self::Composer> {
228 Err(Error::new(
229 ErrorKind::Unsupported,
230 "operation is not supported",
231 ))
232 }
233
234 fn rename(
242 &self,
243 ctx: &OperationContext,
244 from: &str,
245 to: &str,
246 args: OpRename,
247 ) -> impl Future<Output = Result<RpRename>> + MaybeSend;
248
249 fn restore(
259 &self,
260 _ctx: &OperationContext,
261 _path: &str,
262 _args: OpRestore,
263 ) -> impl Future<Output = Result<RpRestore>> + MaybeSend {
264 std::future::ready(Err(Error::new(
265 ErrorKind::Unsupported,
266 "operation is not supported",
267 )))
268 }
269
270 fn presign(
275 &self,
276 ctx: &OperationContext,
277 path: &str,
278 args: OpPresign,
279 ) -> impl Future<Output = Result<RpPresign>> + MaybeSend;
280}
281
282pub trait ServiceDyn: Send + Sync + Debug + Unpin + 'static {
284 fn info_dyn(&self) -> ServiceInfo;
286
287 fn capability_dyn(&self) -> Capability;
289
290 fn create_dir_dyn<'a>(
292 &'a self,
293 ctx: &'a OperationContext,
294 path: &'a str,
295 args: OpCreateDir,
296 ) -> BoxedFuture<'a, Result<RpCreateDir>>;
297
298 fn stat_dyn<'a>(
300 &'a self,
301 ctx: &'a OperationContext,
302 path: &'a str,
303 args: OpStat,
304 ) -> BoxedFuture<'a, Result<RpStat>>;
305
306 fn read_dyn<'a>(
308 &'a self,
309 ctx: &'a OperationContext,
310 path: &'a str,
311 args: OpRead,
312 ) -> Result<oio::Reader>;
313
314 fn write_dyn<'a>(
316 &'a self,
317 ctx: &'a OperationContext,
318 path: &'a str,
319 args: OpWrite,
320 ) -> Result<oio::Writer>;
321
322 fn delete_dyn<'a>(&'a self, ctx: &'a OperationContext) -> Result<oio::Deleter>;
324
325 fn list_dyn<'a>(
327 &'a self,
328 ctx: &'a OperationContext,
329 path: &'a str,
330 args: OpList,
331 ) -> Result<oio::Lister>;
332
333 fn copy_dyn<'a>(
335 &'a self,
336 ctx: &'a OperationContext,
337 from: &'a str,
338 to: &'a str,
339 args: OpCopy,
340 ) -> Result<oio::Copier>;
341
342 fn compose_dyn<'a>(
344 &'a self,
345 ctx: &'a OperationContext,
346 to: &'a str,
347 args: OpCompose,
348 ) -> Result<oio::Composer>;
349
350 fn rename_dyn<'a>(
352 &'a self,
353 ctx: &'a OperationContext,
354 from: &'a str,
355 to: &'a str,
356 args: OpRename,
357 ) -> BoxedFuture<'a, Result<RpRename>>;
358
359 fn restore_dyn<'a>(
361 &'a self,
362 ctx: &'a OperationContext,
363 path: &'a str,
364 args: OpRestore,
365 ) -> BoxedFuture<'a, Result<RpRestore>>;
366
367 fn presign_dyn<'a>(
369 &'a self,
370 ctx: &'a OperationContext,
371 path: &'a str,
372 args: OpPresign,
373 ) -> BoxedFuture<'a, Result<RpPresign>>;
374}
375
376pub type Servicer = Arc<dyn ServiceDyn>;
378
379impl<S: Service + ?Sized> ServiceDyn for S {
380 fn info_dyn(&self) -> ServiceInfo {
381 self.info()
382 }
383
384 fn capability_dyn(&self) -> Capability {
385 self.capability()
386 }
387
388 fn create_dir_dyn<'a>(
389 &'a self,
390 ctx: &'a OperationContext,
391 path: &'a str,
392 args: OpCreateDir,
393 ) -> BoxedFuture<'a, Result<RpCreateDir>> {
394 Box::pin(self.create_dir(ctx, path, args))
395 }
396
397 fn stat_dyn<'a>(
398 &'a self,
399 ctx: &'a OperationContext,
400 path: &'a str,
401 args: OpStat,
402 ) -> BoxedFuture<'a, Result<RpStat>> {
403 Box::pin(self.stat(ctx, path, args))
404 }
405
406 fn read_dyn<'a>(
407 &'a self,
408 ctx: &'a OperationContext,
409 path: &'a str,
410 args: OpRead,
411 ) -> Result<oio::Reader> {
412 Ok(Box::new(self.read(ctx, path, args)?) as oio::Reader)
413 }
414
415 fn write_dyn<'a>(
416 &'a self,
417 ctx: &'a OperationContext,
418 path: &'a str,
419 args: OpWrite,
420 ) -> Result<oio::Writer> {
421 Ok(Box::new(self.write(ctx, path, args)?) as oio::Writer)
422 }
423
424 fn delete_dyn<'a>(&'a self, ctx: &'a OperationContext) -> Result<oio::Deleter> {
425 Ok(Box::new(self.delete(ctx)?) as oio::Deleter)
426 }
427
428 fn list_dyn<'a>(
429 &'a self,
430 ctx: &'a OperationContext,
431 path: &'a str,
432 args: OpList,
433 ) -> Result<oio::Lister> {
434 Ok(Box::new(self.list(ctx, path, args)?) as oio::Lister)
435 }
436
437 fn copy_dyn<'a>(
438 &'a self,
439 ctx: &'a OperationContext,
440 from: &'a str,
441 to: &'a str,
442 args: OpCopy,
443 ) -> Result<oio::Copier> {
444 Ok(Box::new(self.copy(ctx, from, to, args)?) as oio::Copier)
445 }
446
447 fn compose_dyn<'a>(
448 &'a self,
449 ctx: &'a OperationContext,
450 to: &'a str,
451 args: OpCompose,
452 ) -> Result<oio::Composer> {
453 Ok(Box::new(self.compose(ctx, to, args)?) as oio::Composer)
454 }
455
456 fn rename_dyn<'a>(
457 &'a self,
458 ctx: &'a OperationContext,
459 from: &'a str,
460 to: &'a str,
461 args: OpRename,
462 ) -> BoxedFuture<'a, Result<RpRename>> {
463 Box::pin(self.rename(ctx, from, to, args))
464 }
465
466 fn restore_dyn<'a>(
467 &'a self,
468 ctx: &'a OperationContext,
469 path: &'a str,
470 args: OpRestore,
471 ) -> BoxedFuture<'a, Result<RpRestore>> {
472 Box::pin(self.restore(ctx, path, args))
473 }
474
475 fn presign_dyn<'a>(
476 &'a self,
477 ctx: &'a OperationContext,
478 path: &'a str,
479 args: OpPresign,
480 ) -> BoxedFuture<'a, Result<RpPresign>> {
481 Box::pin(self.presign(ctx, path, args))
482 }
483}
484
485impl<T: ServiceDyn + ?Sized> Service for Arc<T> {
487 type Reader = oio::Reader;
488 type Writer = oio::Writer;
489 type Lister = oio::Lister;
490 type Deleter = oio::Deleter;
491 type Copier = oio::Copier;
492 type Composer = oio::Composer;
493
494 fn info(&self) -> ServiceInfo {
495 self.as_ref().info_dyn()
496 }
497
498 fn capability(&self) -> Capability {
499 self.as_ref().capability_dyn()
500 }
501
502 async fn create_dir(
503 &self,
504 ctx: &OperationContext,
505 path: &str,
506 args: OpCreateDir,
507 ) -> Result<RpCreateDir> {
508 self.as_ref().create_dir_dyn(ctx, path, args).await
509 }
510
511 async fn stat(&self, ctx: &OperationContext, path: &str, args: OpStat) -> Result<RpStat> {
512 self.as_ref().stat_dyn(ctx, path, args).await
513 }
514
515 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<oio::Reader> {
516 self.as_ref().read_dyn(ctx, path, args)
517 }
518
519 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<oio::Writer> {
520 self.as_ref().write_dyn(ctx, path, args)
521 }
522
523 fn delete(&self, ctx: &OperationContext) -> Result<oio::Deleter> {
524 self.as_ref().delete_dyn(ctx)
525 }
526
527 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<oio::Lister> {
528 self.as_ref().list_dyn(ctx, path, args)
529 }
530
531 fn copy(
532 &self,
533 ctx: &OperationContext,
534 from: &str,
535 to: &str,
536 args: OpCopy,
537 ) -> Result<oio::Copier> {
538 self.as_ref().copy_dyn(ctx, from, to, args)
539 }
540
541 fn compose(&self, ctx: &OperationContext, to: &str, args: OpCompose) -> Result<oio::Composer> {
542 self.as_ref().compose_dyn(ctx, to, args)
543 }
544
545 async fn rename(
546 &self,
547 ctx: &OperationContext,
548 from: &str,
549 to: &str,
550 args: OpRename,
551 ) -> Result<RpRename> {
552 self.as_ref().rename_dyn(ctx, from, to, args).await
553 }
554
555 async fn restore(
556 &self,
557 ctx: &OperationContext,
558 path: &str,
559 args: OpRestore,
560 ) -> Result<RpRestore> {
561 self.as_ref().restore_dyn(ctx, path, args).await
562 }
563
564 async fn presign(
565 &self,
566 ctx: &OperationContext,
567 path: &str,
568 args: OpPresign,
569 ) -> Result<RpPresign> {
570 self.as_ref().presign_dyn(ctx, path, args).await
571 }
572}
573
574impl Service for () {
576 type Reader = ();
577 type Writer = ();
578 type Lister = ();
579 type Deleter = ();
580 type Copier = ();
581 type Composer = ();
582
583 fn info(&self) -> ServiceInfo {
584 ServiceInfo::with_scheme("dummy")
585 }
586
587 fn capability(&self) -> Capability {
588 Capability::default()
589 }
590
591 async fn create_dir(
592 &self,
593 _: &OperationContext,
594 _: &str,
595 _: OpCreateDir,
596 ) -> Result<RpCreateDir> {
597 Err(Error::new(
598 ErrorKind::Unsupported,
599 "operation is not supported",
600 ))
601 }
602
603 async fn stat(&self, _: &OperationContext, _: &str, _: OpStat) -> Result<RpStat> {
604 Err(Error::new(
605 ErrorKind::Unsupported,
606 "operation is not supported",
607 ))
608 }
609
610 fn read(&self, _: &OperationContext, _: &str, _: OpRead) -> Result<Self::Reader> {
611 Err(Error::new(
612 ErrorKind::Unsupported,
613 "operation is not supported",
614 ))
615 }
616
617 fn write(&self, _: &OperationContext, _: &str, _: OpWrite) -> Result<Self::Writer> {
618 Err(Error::new(
619 ErrorKind::Unsupported,
620 "operation is not supported",
621 ))
622 }
623
624 fn delete(&self, _: &OperationContext) -> Result<Self::Deleter> {
625 Err(Error::new(
626 ErrorKind::Unsupported,
627 "operation is not supported",
628 ))
629 }
630
631 fn list(&self, _: &OperationContext, _: &str, _: OpList) -> Result<Self::Lister> {
632 Err(Error::new(
633 ErrorKind::Unsupported,
634 "operation is not supported",
635 ))
636 }
637
638 fn copy(&self, _: &OperationContext, _: &str, _: &str, _: OpCopy) -> Result<Self::Copier> {
639 Err(Error::new(
640 ErrorKind::Unsupported,
641 "operation is not supported",
642 ))
643 }
644
645 async fn rename(
646 &self,
647 _: &OperationContext,
648 _: &str,
649 _: &str,
650 _: OpRename,
651 ) -> Result<RpRename> {
652 Err(Error::new(
653 ErrorKind::Unsupported,
654 "operation is not supported",
655 ))
656 }
657
658 async fn presign(&self, _: &OperationContext, _: &str, _: OpPresign) -> Result<RpPresign> {
659 Err(Error::new(
660 ErrorKind::Unsupported,
661 "operation is not supported",
662 ))
663 }
664}