opendal_core/raw/oio/compose/api.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::future::Future;
19use std::ops::DerefMut;
20
21use crate::raw::*;
22use crate::*;
23
24/// Composer is a type-erased [`Compose`].
25pub type Composer = Box<dyn ComposeDyn>;
26
27/// Compose accepts ordered source objects and commits one destination object.
28pub trait Compose: Unpin + Send + Sync {
29 /// Accept a complete source object.
30 ///
31 /// A successful return means the source has been accepted in sequence.
32 /// Backend work may still be pending.
33 fn compose<'a>(
34 &'a mut self,
35 path: &'a str,
36 args: OpRead,
37 ) -> impl Future<Output = Result<()>> + MaybeSend + 'a;
38
39 /// Commit all accepted sources and return destination metadata.
40 ///
41 /// Return [`ErrorKind::ConfigInvalid`] if no source has been accepted.
42 fn close(&mut self) -> impl Future<Output = Result<Metadata>> + MaybeSend;
43}
44
45impl Compose for () {
46 async fn compose(&mut self, _: &str, _: OpRead) -> Result<()> {
47 Err(Error::new(
48 ErrorKind::Unsupported,
49 "output composer doesn't support compose",
50 ))
51 }
52
53 async fn close(&mut self) -> Result<Metadata> {
54 Err(Error::new(
55 ErrorKind::Unsupported,
56 "output composer doesn't support close",
57 ))
58 }
59}
60
61/// The dyn version of [`Compose`].
62pub trait ComposeDyn: Unpin + Send + Sync {
63 /// The dyn version of [`Compose::compose`].
64 fn compose_dyn<'a>(&'a mut self, path: &'a str, args: OpRead) -> BoxedFuture<'a, Result<()>>;
65
66 /// The dyn version of [`Compose::close`].
67 fn close_dyn(&mut self) -> BoxedFuture<'_, Result<Metadata>>;
68}
69
70impl<T: Compose + ?Sized> ComposeDyn for T {
71 fn compose_dyn<'a>(&'a mut self, path: &'a str, args: OpRead) -> BoxedFuture<'a, Result<()>> {
72 Box::pin(Compose::compose(self, path, args))
73 }
74
75 fn close_dyn(&mut self) -> BoxedFuture<'_, Result<Metadata>> {
76 Box::pin(self.close())
77 }
78}
79
80impl<T: ComposeDyn + ?Sized> Compose for Box<T> {
81 fn compose<'a>(
82 &'a mut self,
83 path: &'a str,
84 args: OpRead,
85 ) -> impl Future<Output = Result<()>> + MaybeSend + 'a {
86 self.deref_mut().compose_dyn(path, args)
87 }
88
89 async fn close(&mut self) -> Result<Metadata> {
90 self.deref_mut().close_dyn().await
91 }
92}