Skip to main content

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}