opendal_core/raw/oio/copy/
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/// Copier is the type-erased [`Copy`].
25pub type Copier = Box<dyn CopyDyn>;
26
27/// Copy is the trait that OpenDAL returns for stateful copy operations.
28pub trait Copy: Unpin + Send + Sync {
29    /// Drive the copy operation forward.
30    ///
31    /// `Ok(Some(n))` means the copy operation made progress by `n` bytes.
32    /// `Ok(None)` means the copy operation has completed.
33    fn next(&mut self) -> impl Future<Output = Result<Option<usize>>> + MaybeSend;
34
35    /// Close the copier and return metadata from the server-side completion response.
36    fn close(&mut self) -> impl Future<Output = Result<Metadata>> + MaybeSend;
37
38    /// Abort the pending copy operation.
39    fn abort(&mut self) -> impl Future<Output = Result<()>> + MaybeSend;
40}
41
42impl Copy for () {
43    async fn next(&mut self) -> Result<Option<usize>> {
44        Ok(None)
45    }
46
47    async fn close(&mut self) -> Result<Metadata> {
48        Ok(Metadata::default())
49    }
50
51    async fn abort(&mut self) -> Result<()> {
52        Ok(())
53    }
54}
55
56/// OneShotCopier drives a single asynchronous copy step.
57pub struct OneShotCopier {
58    fut: Option<BoxedStaticFuture<Result<Metadata>>>,
59    meta: Option<Metadata>,
60}
61
62/// # Safety
63///
64/// OneShotCopier is only accessed by `&mut self`.
65unsafe impl Sync for OneShotCopier {}
66
67/// # Safety
68///
69/// On wasm targets, futures are local but still only polled through `&mut self`.
70unsafe impl Send for OneShotCopier {}
71
72impl OneShotCopier {
73    /// Create a new one-shot copier.
74    pub fn new(fut: impl Future<Output = Result<Metadata>> + MaybeSend + 'static) -> Self {
75        Self {
76            fut: Some(Box::pin(fut)),
77            meta: None,
78        }
79    }
80
81    /// Create a one-shot copier that has already completed.
82    pub fn completed() -> Self {
83        Self {
84            fut: None,
85            meta: Some(Metadata::default()),
86        }
87    }
88}
89
90impl Copy for OneShotCopier {
91    async fn next(&mut self) -> Result<Option<usize>> {
92        if self.meta.is_none() {
93            self.close().await?;
94        }
95
96        Ok(None)
97    }
98
99    async fn close(&mut self) -> Result<Metadata> {
100        if let Some(fut) = self.fut.take() {
101            self.meta = Some(fut.await?);
102        }
103
104        Ok(self.meta.clone().unwrap_or_default())
105    }
106
107    async fn abort(&mut self) -> Result<()> {
108        self.fut = None;
109        self.meta = None;
110        Ok(())
111    }
112}
113
114/// CopyDyn is the dyn version of [`Copy`].
115pub trait CopyDyn: Unpin + Send + Sync {
116    /// The dyn version of [`Copy::next`].
117    fn next_dyn(&mut self) -> BoxedFuture<'_, Result<Option<usize>>>;
118
119    /// The dyn version of [`Copy::close`].
120    fn close_dyn(&mut self) -> BoxedFuture<'_, Result<Metadata>>;
121
122    /// The dyn version of [`Copy::abort`].
123    fn abort_dyn(&mut self) -> BoxedFuture<'_, Result<()>>;
124}
125
126impl<T: Copy + ?Sized> CopyDyn for T {
127    fn next_dyn(&mut self) -> BoxedFuture<'_, Result<Option<usize>>> {
128        Box::pin(self.next())
129    }
130
131    fn close_dyn(&mut self) -> BoxedFuture<'_, Result<Metadata>> {
132        Box::pin(self.close())
133    }
134
135    fn abort_dyn(&mut self) -> BoxedFuture<'_, Result<()>> {
136        Box::pin(self.abort())
137    }
138}
139
140impl<T: CopyDyn + ?Sized> Copy for Box<T> {
141    async fn next(&mut self) -> Result<Option<usize>> {
142        self.deref_mut().next_dyn().await
143    }
144
145    async fn close(&mut self) -> Result<Metadata> {
146        self.deref_mut().close_dyn().await
147    }
148
149    async fn abort(&mut self) -> Result<()> {
150        self.deref_mut().abort_dyn().await
151    }
152}