This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch new-idea
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git

commit ba345beccca513cb0e580f93048f58306579ff1c
Author: Xuanwo <[email protected]>
AuthorDate: Tue May 23 20:50:07 2023 +0800

    rfc: Add chain based operator API
    
    Signed-off-by: Xuanwo <[email protected]>
---
 .../src/docs/rfcs/0000_chain_based_operator_api.md | 99 ++++++++++++++++++++++
 core/src/docs/rfcs/mod.rs                          |  3 +
 2 files changed, 102 insertions(+)

diff --git a/core/src/docs/rfcs/0000_chain_based_operator_api.md 
b/core/src/docs/rfcs/0000_chain_based_operator_api.md
new file mode 100644
index 00000000..35d6818e
--- /dev/null
+++ b/core/src/docs/rfcs/0000_chain_based_operator_api.md
@@ -0,0 +1,99 @@
+- Proposal Name: `chain_based_operator_api`
+- Start Date: 2023-05-23
+- RFC PR: 
[apache/incubator-opendal#0000](https://github.com/apache/incubator-opendal/pull/0000)
+- Tracking Issue: 
[apache/incubator-opendal#0000](https://github.com/apache/incubator-opendal/issues/0000)
+
+# Summary
+
+Add chain based Operator API to replace `OpXxx`.
+
+# Motivation
+
+OpenDAL provides `xxx_with` API for users to add more options for requests:
+
+```rust
+let bs = op.read_with("path/to/file", 
OpRead::new().with_range(0..=1024)).await?;
+```
+
+However, the API's usability is hindered as users are required to create a new 
`OpXxx` struct. The API call can be excessively verbose:
+
+```rust
+let bs = op.read_with(
+  "path/to/file",
+  OpRead::new()
+    .with_range(0..=1024)
+    .with_if_match("<etag>")
+    .with_if_none_match("<etag>")
+    .with_override_cache_control("<cache_control>")
+    .with_override_content_disposition("<content_disposition>")
+  ).await?;
+```
+
+
+# Guide-level explanation
+
+In this proposal, I plan to introduce chain based `Operator` API to make them 
more firendly to use:
+
+```rust
+let bs = op.read_with("path/to/file")
+  .range(0..=1024)
+  .if_match("<etag>")
+  .if_none_match("<etag>")
+  .override_cache_control("<cache_control>")
+  .override_content_disposition("<content_disposition>")
+  .await?;
+```
+
+By eliminating the usage of `OpXxx`, our users can write code that is more 
readable.
+
+# Reference-level explanation
+
+To implement chain based API, we will change `read_with` as following:
+
+```diff
+- pub async fn read_with(&self, path: &str, args: OpRead) -> Result<Vec<u8>>
++ pub fn read_with(&self, path: &str) -> FutureRead
+```
+
+`FutureRead` will implement `Future<Output=Result<Vec<u8>>>`, so that users 
can still call `read_with` like the following:
+
+```rust
+let bs = op.read_with("path/to/file").await?;
+```
+
+For blocking operations, we will change `read_with` as following:
+
+```diff
+- pub fn read_with(&self, path: &str, args: OpRead) -> Result<Vec<u8>>
++ pub fn read_with(&self, path: &str) -> FunctionRead
+```
+
+`FunctionRead` will implement `call(self) -> Result<Vec<u8>>`, so that users 
can call `read_with` like the following:
+
+```rust
+let bs = op.read_with("path/to/file").call()?;
+```
+
+After this change, all `OpXxx` will be moved as raw API.
+
+# Drawbacks
+
+None
+
+# Rationale and alternatives
+
+None
+
+# Prior art
+
+None
+
+# Unresolved questions
+
+None
+
+# Future possibilities
+
+## Change API after fn_traits stablized
+
+After [fn_traits](https://github.com/rust-lang/rust/issues/29625) get 
stablized, we will implement `FnOnce` for `FunctionXxx` instead of `call`.
diff --git a/core/src/docs/rfcs/mod.rs b/core/src/docs/rfcs/mod.rs
index a27593b0..b73ac282 100644
--- a/core/src/docs/rfcs/mod.rs
+++ b/core/src/docs/rfcs/mod.rs
@@ -139,3 +139,6 @@ pub mod rfc_2083_writer_sink_api {}
 
 #[doc = include_str!("2133_append_api.md")]
 pub mod rfc_2133_append_api {}
+
+#[doc = include_str!("0000_chain_based_operator_api.md")]
+pub mod rfc_0000_chain_based_operator_api {}

Reply via email to