This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 48383aa536 refactor: Implement `IntoFuture` for operator futures to
remove an alloc (#4098)
48383aa536 is described below
commit 48383aa5369afe97533570e40b055769b2ff3484
Author: Xuanwo <[email protected]>
AuthorDate: Tue Jan 30 16:55:07 2024 +0800
refactor: Implement `IntoFuture` for operator futures to remove an alloc
(#4098)
* Save work
Signed-off-by: Xuanwo <[email protected]>
* Save
Signed-off-by: Xuanwo <[email protected]>
* Fix build
Signed-off-by: Xuanwo <[email protected]>
---------
Signed-off-by: Xuanwo <[email protected]>
---
core/src/types/operator/operator.rs | 315 +++++++--------
core/src/types/operator/operator_futures.rs | 583 +++++++---------------------
2 files changed, 286 insertions(+), 612 deletions(-)
diff --git a/core/src/types/operator/operator.rs
b/core/src/types/operator/operator.rs
index 8ba9899b84..8c50d7db4c 100644
--- a/core/src/types/operator/operator.rs
+++ b/core/src/types/operator/operator.rs
@@ -15,6 +15,7 @@
// specific language governing permissions and limitations
// under the License.
+use std::future::Future;
use std::time::Duration;
use bytes::Buf;
@@ -280,24 +281,18 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn stat_with(&self, path: &str) -> FutureStat {
+ pub fn stat_with(&self, path: &str) -> FutureStat<impl Future<Output =
Result<Metadata>>> {
let path = normalize_path(path);
- let fut = FutureStat(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpStat::default(),
- |inner, path, args| {
- let fut = async move {
- let rp = inner.stat(&path, args).await?;
- Ok(rp.into_metadata())
- };
-
- Box::pin(fut)
+ |inner, path, args| async move {
+ let rp = inner.stat(&path, args).await?;
+ Ok(rp.into_metadata())
},
- ));
-
- fut
+ )
}
/// Check if this path exists or not.
@@ -409,50 +404,43 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn read_with(&self, path: &str) -> FutureRead {
+ pub fn read_with(&self, path: &str) -> FutureRead<impl Future<Output =
Result<Vec<u8>>>> {
let path = normalize_path(path);
- let fut = FutureRead(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpRead::default(),
- |inner, path, args| {
- let fut = async move {
- if !validate_path(&path, EntryMode::FILE) {
- return Err(Error::new(
- ErrorKind::IsADirectory,
- "read path is a directory",
- )
- .with_operation("read")
- .with_context("service", inner.info().scheme())
- .with_context("path", &path));
- }
-
- let range = args.range();
- let (size_hint, range) = if let Some(size) = range.size() {
- (size, range)
- } else {
- let size = inner
- .stat(&path, OpStat::default())
- .await?
- .into_metadata()
- .content_length();
- let range = range.complete(size);
- (range.size().unwrap(), range)
- };
-
- let (_, mut s) = inner.read(&path,
args.with_range(range)).await?;
- let mut buf = Vec::with_capacity(size_hint as usize);
- s.read_to_end(&mut buf).await?;
-
- Ok(buf)
+ |inner, path, args| async move {
+ if !validate_path(&path, EntryMode::FILE) {
+ return Err(
+ Error::new(ErrorKind::IsADirectory, "read path is a
directory")
+ .with_operation("read")
+ .with_context("service", inner.info().scheme())
+ .with_context("path", &path),
+ );
+ }
+
+ let range = args.range();
+ let (size_hint, range) = if let Some(size) = range.size() {
+ (size, range)
+ } else {
+ let size = inner
+ .stat(&path, OpStat::default())
+ .await?
+ .into_metadata()
+ .content_length();
+ let range = range.complete(size);
+ (range.size().unwrap(), range)
};
- Box::pin(fut)
- },
- ));
+ let (_, mut s) = inner.read(&path,
args.with_range(range)).await?;
+ let mut buf = Vec::with_capacity(size_hint as usize);
+ s.read_to_end(&mut buf).await?;
- fut
+ Ok(buf)
+ },
+ )
}
/// Create a new reader which can read the whole path.
@@ -489,32 +477,26 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn reader_with(&self, path: &str) -> FutureReader {
+ pub fn reader_with(&self, path: &str) -> FutureRead<impl Future<Output =
Result<Reader>>> {
let path = normalize_path(path);
- let fut = FutureReader(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpRead::default(),
- |inner, path, args| {
- let fut = async move {
- if !validate_path(&path, EntryMode::FILE) {
- return Err(Error::new(
- ErrorKind::IsADirectory,
- "read path is a directory",
- )
- .with_operation("Operator::reader")
- .with_context("service", inner.info().scheme())
- .with_context("path", path));
- }
-
- Reader::create(inner.clone(), &path, args).await
- };
+ |inner, path, args| async move {
+ if !validate_path(&path, EntryMode::FILE) {
+ return Err(
+ Error::new(ErrorKind::IsADirectory, "read path is a
directory")
+ .with_operation("Operator::reader")
+ .with_context("service", inner.info().scheme())
+ .with_context("path", path),
+ );
+ }
- Box::pin(fut)
+ Reader::create(inner.clone(), &path, args).await
},
- ));
- fut
+ )
}
/// Write bytes into path.
@@ -711,32 +693,26 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn writer_with(&self, path: &str) -> FutureWriter {
+ pub fn writer_with(&self, path: &str) -> FutureWriter<impl Future<Output =
Result<Writer>>> {
let path = normalize_path(path);
- let fut = FutureWriter(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpWrite::default(),
- |inner, path, args| {
- let fut = async move {
- if !validate_path(&path, EntryMode::FILE) {
- return Err(Error::new(
- ErrorKind::IsADirectory,
- "write path is a directory",
- )
- .with_operation("Operator::writer")
- .with_context("service",
inner.info().scheme().into_static())
- .with_context("path", &path));
- }
-
- Writer::create(inner, &path, args).await
- };
- Box::pin(fut)
- },
- ));
+ |inner, path, args| async move {
+ if !validate_path(&path, EntryMode::FILE) {
+ return Err(
+ Error::new(ErrorKind::IsADirectory, "write path is a
directory")
+ .with_operation("Operator::writer")
+ .with_context("service",
inner.info().scheme().into_static())
+ .with_context("path", &path),
+ );
+ }
- fut
+ Writer::create(inner, &path, args).await
+ },
+ )
}
/// Write data with extra options.
@@ -762,40 +738,39 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn write_with(&self, path: &str, bs: impl Into<Bytes>) -> FutureWrite {
+ pub fn write_with(
+ &self,
+ path: &str,
+ bs: impl Into<Bytes>,
+ ) -> FutureWrite<impl Future<Output = Result<()>>> {
let path = normalize_path(path);
let bs = bs.into();
- let fut = FutureWrite(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
(OpWrite::default(), bs),
- |inner, path, (args, mut bs)| {
- let fut = async move {
- if !validate_path(&path, EntryMode::FILE) {
- return Err(Error::new(
- ErrorKind::IsADirectory,
- "write path is a directory",
- )
- .with_operation("Operator::write_with")
- .with_context("service",
inner.info().scheme().into_static())
- .with_context("path", &path));
- }
-
- let (_, mut w) = inner.write(&path, args).await?;
- while bs.remaining() > 0 {
- let n = w.write(&bs).await?;
- bs.advance(n);
- }
-
- w.close().await?;
-
- Ok(())
- };
- Box::pin(fut)
+ |inner, path, (args, mut bs)| async move {
+ if !validate_path(&path, EntryMode::FILE) {
+ return Err(
+ Error::new(ErrorKind::IsADirectory, "write path is a
directory")
+ .with_operation("Operator::write_with")
+ .with_context("service",
inner.info().scheme().into_static())
+ .with_context("path", &path),
+ );
+ }
+
+ let (_, mut w) = inner.write(&path, args).await?;
+ while bs.remaining() > 0 {
+ let n = w.write(&bs).await?;
+ bs.advance(n);
+ }
+
+ w.close().await?;
+
+ Ok(())
},
- ));
- fut
+ )
}
/// Delete the given path.
@@ -839,24 +814,18 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn delete_with(&self, path: &str) -> FutureDelete {
+ pub fn delete_with(&self, path: &str) -> FutureDelete<impl Future<Output =
Result<()>>> {
let path = normalize_path(path);
- let fut = FutureDelete(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpDelete::default(),
- |inner, path, args| {
- let fut = async move {
- let _ = inner.delete(&path, args).await?;
- Ok(())
- };
-
- Box::pin(fut)
+ |inner, path, args| async move {
+ let _ = inner.delete(&path, args).await?;
+ Ok(())
},
- ));
-
- fut
+ )
}
///
@@ -1253,23 +1222,19 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn list_with(&self, path: &str) -> FutureList {
+ pub fn list_with(&self, path: &str) -> FutureList<impl Future<Output =
Result<Vec<Entry>>>> {
let path = normalize_path(path);
- let fut = FutureList(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpList::default(),
- |inner, path, args| {
- let fut = async move {
- let lister = Lister::create(inner, &path, args).await?;
+ |inner, path, args| async move {
+ let lister = Lister::create(inner, &path, args).await?;
- lister.try_collect().await
- };
- Box::pin(fut)
+ lister.try_collect().await
},
- ));
- fut
+ )
}
/// List entries that starts with given `path` in parent dir.
@@ -1474,19 +1439,15 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn lister_with(&self, path: &str) -> FutureLister {
+ pub fn lister_with(&self, path: &str) -> FutureList<impl Future<Output =
Result<Lister>>> {
let path = normalize_path(path);
- let fut = FutureLister(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
OpList::default(),
- |inner, path, args| {
- let fut = async move { Lister::create(inner, &path,
args).await };
- Box::pin(fut)
- },
- ));
- fut
+ |inner, path, args| async move { Lister::create(inner, &path,
args).await },
+ )
}
}
@@ -1538,23 +1499,23 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn presign_stat_with(&self, path: &str, expire: Duration) ->
FuturePresignStat {
+ pub fn presign_stat_with(
+ &self,
+ path: &str,
+ expire: Duration,
+ ) -> FuturePresignStat<impl Future<Output = Result<PresignedRequest>>> {
let path = normalize_path(path);
- let fut = FuturePresignStat(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
(OpStat::default(), expire),
- |inner, path, (args, dur)| {
- let fut = async move {
- let op = OpPresign::new(args, dur);
- let rp = inner.presign(&path, op).await?;
- Ok(rp.into_presigned_request())
- };
- Box::pin(fut)
+ |inner, path, (args, dur)| async move {
+ let op = OpPresign::new(args, dur);
+ let rp = inner.presign(&path, op).await?;
+ Ok(rp.into_presigned_request())
},
- ));
- fut
+ )
}
/// Presign an operation for read.
@@ -1613,23 +1574,23 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn presign_read_with(&self, path: &str, expire: Duration) ->
FuturePresignRead {
+ pub fn presign_read_with(
+ &self,
+ path: &str,
+ expire: Duration,
+ ) -> FuturePresignRead<impl Future<Output = Result<PresignedRequest>>> {
let path = normalize_path(path);
- let fut = FuturePresignRead(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
(OpRead::default(), expire),
- |inner, path, (args, dur)| {
- let fut = async move {
- let op = OpPresign::new(args, dur);
- let rp = inner.presign(&path, op).await?;
- Ok(rp.into_presigned_request())
- };
- Box::pin(fut)
+ |inner, path, (args, dur)| async move {
+ let op = OpPresign::new(args, dur);
+ let rp = inner.presign(&path, op).await?;
+ Ok(rp.into_presigned_request())
},
- ));
- fut
+ )
}
/// Presign an operation for write.
@@ -1686,22 +1647,22 @@ impl Operator {
/// # Ok(())
/// # }
/// ```
- pub fn presign_write_with(&self, path: &str, expire: Duration) ->
FuturePresignWrite {
+ pub fn presign_write_with(
+ &self,
+ path: &str,
+ expire: Duration,
+ ) -> FuturePresignWrite<impl Future<Output = Result<PresignedRequest>>> {
let path = normalize_path(path);
- let fut = FuturePresignWrite(OperatorFuture::new(
+ OperatorFuture::new(
self.inner().clone(),
path,
(OpWrite::default(), expire),
- |inner, path, (args, dur)| {
- let fut = async move {
- let op = OpPresign::new(args, dur);
- let rp = inner.presign(&path, op).await?;
- Ok(rp.into_presigned_request())
- };
- Box::pin(fut)
+ |inner, path, (args, dur)| async move {
+ let op = OpPresign::new(args, dur);
+ let rp = inner.presign(&path, op).await?;
+ Ok(rp.into_presigned_request())
},
- ));
- fut
+ )
}
}
diff --git a/core/src/types/operator/operator_futures.rs
b/core/src/types/operator/operator_futures.rs
index d8c090a618..15ce16e0c6 100644
--- a/core/src/types/operator/operator_futures.rs
+++ b/core/src/types/operator/operator_futures.rs
@@ -19,418 +19,242 @@
//!
//! By using futures, users can add more options for operation.
-use std::mem;
+use std::future::IntoFuture;
use std::ops::RangeBounds;
-use std::pin::Pin;
-use std::task::Context;
-use std::task::Poll;
use std::time::Duration;
use bytes::Bytes;
use flagset::FlagSet;
use futures::Future;
-use futures::FutureExt;
use crate::raw::*;
use crate::*;
/// OperatorFuture is the future generated by [`Operator`].
///
-/// The future will consume all the input to generate a result.
-pub(crate) enum OperatorFuture<T, F> {
- /// Idle state, waiting for the future to be polled
- Idle(
- /// The accessor to the underlying object storage
- FusedAccessor,
- /// The path of string
- String,
- /// The input args
- T,
- /// The function which will move all the args and return a static
future
- fn(FusedAccessor, String, T) -> BoxedFuture<Result<F>>,
- ),
- /// Polling state, waiting for the future to be ready
- Poll(BoxedFuture<Result<F>>),
- /// Empty state, the future has been polled and completed or
- /// something is broken during state switch.
- Empty,
+/// The future will consume all the input to generate a future.
+///
+/// # NOTES
+///
+/// This struct is by design to keep in crate. We don't want
+/// users to use this struct directly.
+pub struct OperatorFuture<T, F> {
+ /// The accessor to the underlying object storage
+ acc: FusedAccessor,
+ /// The path of string
+ path: String,
+ /// The input args
+ args: T,
+ /// The function which will move all the args and return a static future
+ f: fn(FusedAccessor, String, T) -> F,
}
-impl<T, F> OperatorFuture<T, F> {
- pub fn new(
+impl<T, F: Future> OperatorFuture<T, F> {
+ /// # NOTES
+ ///
+ /// This struct is by design to keep in crate. We don't want
+ /// users to use this struct directly.
+ pub(crate) fn new(
inner: FusedAccessor,
path: String,
args: T,
- f: fn(FusedAccessor, String, T) -> BoxedFuture<Result<F>>,
+ f: fn(FusedAccessor, String, T) -> F,
) -> Self {
- OperatorFuture::Idle(inner, path, args, f)
+ OperatorFuture {
+ acc: inner,
+ path,
+ args,
+ f,
+ }
}
+}
- fn map_args(self, f: impl FnOnce(T) -> T) -> Self {
- match self {
- OperatorFuture::Idle(inner, path, args, func) => {
- OperatorFuture::Idle(inner, path, f(args), func)
- }
- _ => unreachable!("future has been polled and should not be
changed again"),
- }
+impl<T, F> OperatorFuture<T, F> {
+ /// Change the operation's args.
+ fn map(mut self, f: impl FnOnce(T) -> T) -> Self {
+ self.args = (f)(self.args);
+ self
}
}
-impl<T, F> Future for OperatorFuture<T, F>
+impl<T, F> IntoFuture for OperatorFuture<T, F>
where
- T: Unpin,
- F: Unpin,
+ F: Future,
{
- type Output = Result<F>;
+ type Output = F::Output;
+ type IntoFuture = F;
- /// We will move the self state out by replace a `Empty` into.
- ///
- /// - If the future is `Idle`, we will move all args out to build
- /// a new future, and update self state to `Poll`.
- /// - If the future is `Poll`, we will poll the inner future
- /// - If future is `Ready`, we will return it directly with
- /// self state is `Empty`
- /// - If future is `Pending`, we will set self state to `Poll`
- /// and wait for next poll
- ///
- /// In general, `Empty` state should not be polled.
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- loop {
- match mem::replace(self.as_mut().get_mut(), OperatorFuture::Empty)
{
- OperatorFuture::Idle(inner, path, args, f) => {
- *self = OperatorFuture::Poll(f(inner, path, args))
- }
- OperatorFuture::Poll(mut fut) => match fut.as_mut().poll(cx) {
- Poll::Ready(v) => return Poll::Ready(v),
- Poll::Pending => {
- *self = OperatorFuture::Poll(fut);
- return Poll::Pending;
- }
- },
- OperatorFuture::Empty => {
- panic!("future polled after completion");
- }
- }
- }
+ fn into_future(self) -> Self::IntoFuture {
+ (self.f)(self.acc, self.path, self.args)
}
}
/// Future that generated by [`Operator::stat_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FutureStat(pub(crate) OperatorFuture<OpStat, Metadata>);
+pub type FutureStat<F> = OperatorFuture<OpStat, F>;
-impl FutureStat {
+impl<F> FutureStat<F> {
/// Set the If-Match for this operation.
- pub fn if_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_if_match(v));
- self
+ pub fn if_match(self, v: &str) -> Self {
+ self.map(|args| args.with_if_match(v))
}
/// Set the If-None-Match for this operation.
- pub fn if_none_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_if_none_match(v));
- self
+ pub fn if_none_match(self, v: &str) -> Self {
+ self.map(|args| args.with_if_none_match(v))
}
/// Set the version for this operation.
- pub fn version(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_version(v));
- self
- }
-}
-
-impl Future for FutureStat {
- type Output = Result<Metadata>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn version(self, v: &str) -> Self {
+ self.map(|args| args.with_version(v))
}
}
/// Future that generated by [`Operator::presign_stat_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FuturePresignStat(pub(crate) OperatorFuture<(OpStat, Duration),
PresignedRequest>);
+pub type FuturePresignStat<F> = OperatorFuture<(OpStat, Duration), F>;
-impl FuturePresignStat {
+impl<F> FuturePresignStat<F> {
/// Sets the content-disposition header that should be send back by the
remote read operation.
- pub fn override_content_disposition(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)|
(args.with_override_content_disposition(v), dur));
- self
+ pub fn override_content_disposition(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_override_content_disposition(v),
dur))
}
/// Sets the cache-control header that should be send back by the remote
read operation.
- pub fn override_cache_control(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_override_cache_control(v),
dur));
- self
+ pub fn override_cache_control(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_override_cache_control(v), dur))
}
/// Sets the content-type header that should be send back by the remote
read operation.
- pub fn override_content_type(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_override_content_type(v), dur));
- self
+ pub fn override_content_type(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_override_content_type(v), dur))
}
/// Set the If-Match of the option
- pub fn if_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|(args, dur)| (args.with_if_match(v), dur));
- self
+ pub fn if_match(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_if_match(v), dur))
}
/// Set the If-None-Match of the option
- pub fn if_none_match(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_if_none_match(v), dur));
- self
- }
-}
-
-impl Future for FuturePresignStat {
- type Output = Result<PresignedRequest>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn if_none_match(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_if_none_match(v), dur))
}
}
/// Future that generated by [`Operator::presign_read_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FuturePresignRead(pub(crate) OperatorFuture<(OpRead, Duration),
PresignedRequest>);
+pub type FuturePresignRead<F> = OperatorFuture<(OpRead, Duration), F>;
-impl FuturePresignRead {
+impl<F> FuturePresignRead<F> {
/// Create a new OpRead with range.
- pub fn range(mut self, v: BytesRange) -> Self {
- self.0 = self.0.map_args(|(args, dur)| (args.with_range(v), dur));
- self
+ pub fn range(self, v: BytesRange) -> Self {
+ self.map(|(args, dur)| (args.with_range(v), dur))
}
/// Sets the content-disposition header that should be send back by the
remote read operation.
- pub fn override_content_disposition(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)|
(args.with_override_content_disposition(v), dur));
- self
+ pub fn override_content_disposition(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_override_content_disposition(v),
dur))
}
/// Sets the cache-control header that should be send back by the remote
read operation.
- pub fn override_cache_control(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_override_cache_control(v),
dur));
- self
+ pub fn override_cache_control(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_override_cache_control(v), dur))
}
/// Sets the content-type header that should be send back by the remote
read operation.
- pub fn override_content_type(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_override_content_type(v), dur));
- self
+ pub fn override_content_type(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_override_content_type(v), dur))
}
/// Set the If-Match of the option
- pub fn if_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|(args, dur)| (args.with_if_match(v), dur));
- self
+ pub fn if_match(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_if_match(v), dur))
}
/// Set the If-None-Match of the option
- pub fn if_none_match(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_if_none_match(v), dur));
- self
- }
-}
-
-impl Future for FuturePresignRead {
- type Output = Result<PresignedRequest>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn if_none_match(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_if_none_match(v), dur))
}
}
/// Future that generated by [`Operator::presign_write_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FuturePresignWrite(pub(crate) OperatorFuture<(OpWrite, Duration),
PresignedRequest>);
+pub type FuturePresignWrite<F> = OperatorFuture<(OpWrite, Duration), F>;
-impl FuturePresignWrite {
+impl<F> FuturePresignWrite<F> {
/// Set the content type of option
- pub fn content_type(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_content_type(v), dur));
- self
+ pub fn content_type(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_content_type(v), dur))
}
/// Set the content disposition of option
- pub fn content_disposition(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_content_disposition(v), dur));
- self
+ pub fn content_disposition(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_content_disposition(v), dur))
}
/// Set the content type of option
- pub fn cache_control(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, dur)| (args.with_cache_control(v), dur));
- self
+ pub fn cache_control(self, v: &str) -> Self {
+ self.map(|(args, dur)| (args.with_cache_control(v), dur))
}
}
-impl Future for FuturePresignWrite {
- type Output = Result<PresignedRequest>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
- }
-}
-
-/// Future that generated by [`Operator::read_with`].
+/// Future that generated by [`Operator::read_with`] or
[`Operator::reader_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FutureRead(pub(crate) OperatorFuture<OpRead, Vec<u8>>);
+pub type FutureRead<F> = OperatorFuture<OpRead, F>;
-impl FutureRead {
+impl<F> FutureRead<F> {
/// Set the range header for this operation.
- pub fn range(mut self, range: impl RangeBounds<u64>) -> Self {
- self.0 = self.0.map_args(|args| args.with_range(range.into()));
- self
+ pub fn range(self, range: impl RangeBounds<u64>) -> Self {
+ self.map(|args| args.with_range(range.into()))
}
/// Sets the content-disposition header that should be send back by the
remote read operation.
- pub fn override_content_disposition(mut self, content_disposition: &str)
-> Self {
- self.0 = self
- .0
- .map_args(|args|
args.with_override_content_disposition(content_disposition));
- self
+ pub fn override_content_disposition(self, v: &str) -> Self {
+ self.map(|args| args.with_override_content_disposition(v))
}
/// Sets the cache-control header that should be send back by the remote
read operation.
- pub fn override_cache_control(mut self, cache_control: &str) -> Self {
- self.0 = self
- .0
- .map_args(|args| args.with_override_cache_control(cache_control));
- self
+ pub fn override_cache_control(self, v: &str) -> Self {
+ self.map(|args| args.with_override_cache_control(v))
}
/// Sets the content-type header that should be send back by the remote
read operation.
- pub fn override_content_type(mut self, content_type: &str) -> Self {
- self.0 = self
- .0
- .map_args(|args| args.with_override_content_type(content_type));
- self
+ pub fn override_content_type(self, v: &str) -> Self {
+ self.map(|args| args.with_override_content_type(v))
}
/// Set the If-Match for this operation.
- pub fn if_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_if_match(v));
- self
+ pub fn if_match(self, v: &str) -> Self {
+ self.map(|args| args.with_if_match(v))
}
/// Set the If-None-Match for this operation.
- pub fn if_none_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_if_none_match(v));
- self
+ pub fn if_none_match(self, v: &str) -> Self {
+ self.map(|args| args.with_if_none_match(v))
}
/// Set the version for this operation.
- pub fn version(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_version(v));
- self
+ pub fn version(self, v: &str) -> Self {
+ self.map(|args| args.with_version(v))
}
-}
-
-impl Future for FutureRead {
- type Output = Result<Vec<u8>>;
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
- }
-}
-
-/// Future that generated by [`Operator::reader_with`].
-///
-/// Users can add more options by public functions provided by this struct.
-pub struct FutureReader(pub(crate) OperatorFuture<OpRead, Reader>);
-
-impl FutureReader {
- /// Set the range header for this operation.
- pub fn range(mut self, range: impl RangeBounds<u64>) -> Self {
- self.0 = self.0.map_args(|args| args.with_range(range.into()));
- self
- }
-
- /// Sets the content-disposition header that should be send back by the
remote read operation.
- pub fn override_content_disposition(mut self, content_disposition: &str)
-> Self {
- self.0 = self
- .0
- .map_args(|args|
args.with_override_content_disposition(content_disposition));
- self
- }
-
- /// Sets the cache-control header that should be send back by the remote
read operation.
- pub fn override_cache_control(mut self, cache_control: &str) -> Self {
- self.0 = self
- .0
- .map_args(|args| args.with_override_cache_control(cache_control));
- self
- }
-
- /// Sets the content-type header that should be send back by the remote
read operation.
- pub fn override_content_type(mut self, content_type: &str) -> Self {
- self.0 = self
- .0
- .map_args(|args| args.with_override_content_type(content_type));
- self
- }
-
- /// Set the If-Match for this operation.
- pub fn if_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_if_match(v));
- self
- }
-
- /// Set the If-None-Match for this operation.
- pub fn if_none_match(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_if_none_match(v));
- self
- }
-
- /// Set the buffer capability to enable `BufferReader`.
- pub fn buffer(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|args| args.with_buffer(v));
- self
- }
-}
-
-impl Future for FutureReader {
- type Output = Result<Reader>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ /// Set the buffer capability to enable buffer for reader.
+ pub fn buffer(self, v: usize) -> Self {
+ self.map(|args| args.with_buffer(v))
}
}
/// Future that generated by [`Operator::write_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FutureWrite(pub(crate) OperatorFuture<(OpWrite, Bytes), ()>);
+pub type FutureWrite<F> = OperatorFuture<(OpWrite, Bytes), F>;
-impl FutureWrite {
+impl<F> FutureWrite<F> {
/// Set the append mode of op.
///
/// If the append mode is set, the data will be appended to the end of the
file.
@@ -438,9 +262,8 @@ impl FutureWrite {
/// # Notes
///
/// Service could return `Unsupported` if the underlying storage does not
support append.
- pub fn append(mut self, v: bool) -> Self {
- self.0 = self.0.map_args(|(args, bs)| (args.with_append(v), bs));
- self
+ pub fn append(self, v: bool) -> Self {
+ self.map(|(args, bs)| (args.with_append(v), bs))
}
/// Set the buffer size of op.
@@ -451,56 +274,37 @@ impl FutureWrite {
///
/// Service could have their own minimum buffer size while perform write
operations like
/// multipart uploads. So the buffer size may be larger than the given
buffer size.
- pub fn buffer(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|(args, bs)| (args.with_buffer(v), bs));
- self
+ pub fn buffer(self, v: usize) -> Self {
+ self.map(|(args, bs)| (args.with_buffer(v), bs))
}
/// Set the content type of option
- pub fn content_type(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, bs)| (args.with_content_type(v), bs));
- self
+ pub fn content_type(self, v: &str) -> Self {
+ self.map(|(args, bs)| (args.with_content_type(v), bs))
}
/// Set the content disposition of option
- pub fn content_disposition(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, bs)| (args.with_content_disposition(v), bs));
- self
+ pub fn content_disposition(self, v: &str) -> Self {
+ self.map(|(args, bs)| (args.with_content_disposition(v), bs))
}
/// Set the content type of option
- pub fn cache_control(mut self, v: &str) -> Self {
- self.0 = self
- .0
- .map_args(|(args, bs)| (args.with_cache_control(v), bs));
- self
+ pub fn cache_control(self, v: &str) -> Self {
+ self.map(|(args, bs)| (args.with_cache_control(v), bs))
}
/// Set the maximum concurrent write task amount.
- pub fn concurrent(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|(args, bs)| (args.with_buffer(v), bs));
- self
- }
-}
-
-impl Future for FutureWrite {
- type Output = Result<()>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn concurrent(self, v: usize) -> Self {
+ self.map(|(args, bs)| (args.with_buffer(v), bs))
}
}
/// Future that generated by [`Operator::writer_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FutureWriter(pub(crate) OperatorFuture<OpWrite, Writer>);
+pub type FutureWriter<F> = OperatorFuture<OpWrite, F>;
-impl FutureWriter {
+impl<F> FutureWriter<F> {
/// Set the append mode of op.
///
/// If the append mode is set, the data will be appended to the end of the
file.
@@ -508,9 +312,8 @@ impl FutureWriter {
/// ## Notes
///
/// Service could return `Unsupported` if the underlying storage does not
support append.
- pub fn append(mut self, v: bool) -> Self {
- self.0 = self.0.map_args(|args| args.with_append(v));
- self
+ pub fn append(self, v: bool) -> Self {
+ self.map(|args| args.with_append(v))
}
/// Set the buffer size of op.
@@ -528,85 +331,61 @@ impl FutureWriter {
/// - GCS requires the part size to be aligned with 256 KiB.
///
/// The services will alter the buffer size to meet their requirements.
- pub fn buffer(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|args| args.with_buffer(v));
- self
+ pub fn buffer(self, v: usize) -> Self {
+ self.map(|args| args.with_buffer(v))
}
/// Set the content type of option
- pub fn content_type(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_content_type(v));
- self
+ pub fn content_type(self, v: &str) -> Self {
+ self.map(|args| args.with_content_type(v))
}
/// Set the content disposition of option
- pub fn content_disposition(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_content_disposition(v));
- self
+ pub fn content_disposition(self, v: &str) -> Self {
+ self.map(|args| args.with_content_disposition(v))
}
/// Set the content type of option
- pub fn cache_control(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_cache_control(v));
- self
+ pub fn cache_control(self, v: &str) -> Self {
+ self.map(|args| args.with_cache_control(v))
}
/// Set the maximum concurrent write task amount.
- pub fn concurrent(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|args| args.with_concurrent(v));
- self
- }
-}
-
-impl Future for FutureWriter {
- type Output = Result<Writer>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn concurrent(self, v: usize) -> Self {
+ self.map(|args| args.with_concurrent(v))
}
}
/// Future that generated by [`Operator::delete_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FutureDelete(pub(crate) OperatorFuture<OpDelete, ()>);
+pub type FutureDelete<F> = OperatorFuture<OpDelete, F>;
-impl FutureDelete {
+impl<F> FutureDelete<F> {
/// Change the version of this delete operation.
- pub fn version(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_version(v));
- self
- }
-}
-
-impl Future for FutureDelete {
- type Output = Result<()>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn version(self, v: &str) -> Self {
+ self.map(|args| args.with_version(v))
}
}
-/// Future that generated by [`Operator::list_with`].
+/// Future that generated by [`Operator::list_with`] or
[`Operator::lister_with`].
///
/// Users can add more options by public functions provided by this struct.
-pub struct FutureList(pub(crate) OperatorFuture<OpList, Vec<Entry>>);
+pub type FutureList<F> = OperatorFuture<OpList, F>;
-impl FutureList {
+impl<F> FutureList<F> {
/// The limit passed to underlying service to specify the max results
/// that could return per-request.
///
/// Users could use this to control the memory usage of list operation.
- pub fn limit(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|args| args.with_limit(v));
- self
+ pub fn limit(self, v: usize) -> Self {
+ self.map(|args| args.with_limit(v))
}
/// The start_after passes to underlying service to specify the specified
key
/// to start listing from.
- pub fn start_after(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_start_after(v));
- self
+ pub fn start_after(self, v: &str) -> Self {
+ self.map(|args| args.with_start_after(v))
}
/// The recursive is used to control whether the list operation is
recursive.
@@ -615,9 +394,8 @@ impl FutureList {
/// - If `true`, list operation will list all entries that starts with
given path.
///
/// Default to `false`.
- pub fn recursive(mut self, v: bool) -> Self {
- self.0 = self.0.map_args(|args| args.with_recursive(v));
- self
+ pub fn recursive(self, v: bool) -> Self {
+ self.map(|args| args.with_recursive(v))
}
/// Metakey is used to control which meta should be returned.
@@ -628,64 +406,8 @@ impl FutureList {
/// - `None` means services doesn't have this meta.
///
/// The default metakey is `Metakey::Mode`.
- pub fn metakey(mut self, v: impl Into<FlagSet<Metakey>>) -> Self {
- self.0 = self.0.map_args(|args| args.with_metakey(v));
- self
- }
-}
-
-impl Future for FutureList {
- type Output = Result<Vec<Entry>>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
- }
-}
-
-/// Future that generated by [`Operator::lister_with`].
-///
-/// Users can add more options by public functions provided by this struct.
-pub struct FutureLister(pub(crate) OperatorFuture<OpList, Lister>);
-
-impl FutureLister {
- /// The limit passed to underlying service to specify the max results
- /// that could return per-request.
- ///
- /// Users could use this to control the memory usage of list operation.
- pub fn limit(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|args| args.with_limit(v));
- self
- }
-
- /// The start_after passes to underlying service to specify the specified
key
- /// to start listing from.
- pub fn start_after(mut self, v: &str) -> Self {
- self.0 = self.0.map_args(|args| args.with_start_after(v));
- self
- }
-
- /// The recursive is used to control whether the list operation is
recursive.
- ///
- /// - If `false`, list operation will only list the entries under the
given path.
- /// - If `true`, list operation will list all entries that starts with
given path.
- ///
- /// Default to `false`.
- pub fn recursive(mut self, v: bool) -> Self {
- self.0 = self.0.map_args(|args| args.with_recursive(v));
- self
- }
-
- /// Metakey is used to control which meta should be returned.
- ///
- /// Lister will make sure the result for specified meta is **known**:
- ///
- /// - `Some(v)` means exist.
- /// - `None` means services doesn't have this meta.
- ///
- /// The default metakey is `Metakey::Mode`.
- pub fn metakey(mut self, v: impl Into<FlagSet<Metakey>>) -> Self {
- self.0 = self.0.map_args(|args| args.with_metakey(v));
- self
+ pub fn metakey(self, v: impl Into<FlagSet<Metakey>>) -> Self {
+ self.map(|args| args.with_metakey(v))
}
/// Concurrent is used to control the number of concurrent stat requests.
@@ -693,16 +415,7 @@ impl FutureLister {
/// If concurrent is set to <=1, the lister will perform stat requests
sequentially.
///
/// The default concurrent is 1.
- pub fn concurrent(mut self, v: usize) -> Self {
- self.0 = self.0.map_args(|args| args.with_concurrent(v));
- self
- }
-}
-
-impl Future for FutureLister {
- type Output = Result<Lister>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) ->
Poll<Self::Output> {
- self.0.poll_unpin(cx)
+ pub fn concurrent(self, v: usize) -> Self {
+ self.map(|args| args.with_concurrent(v))
}
}