Repository: apache/opendal (language: rust)

Issue:
bug: object_store_opendal does not compile on wasm32-unknown-unknown
### Describe the bug

Doesn't compile on my machine with wasm32-unknown-unknown

### Steps to Reproduce

```
cd integrations/object_store
cargo build  --release --target wasm32-unknown-unknown --features "send_wrapper"
```

Will see:
```
error[E0277]: `dyn futures::Future<Output = ()>` cannot be sent between threads safely
    --> /opendal/core/src/types/execute/executors/tokio_executor.rs:28:42
     |
28   |         let _handle = tokio::task::spawn(f);
     |                       ------------------ ^ `dyn futures::Future<Output = ()>` cannot be sent between threads safely
     |                       |
     |                       required by a bound introduced by this call
     |
     = help: the trait `std::marker::Send` is not implemented for `dyn futures::Future<Output = ()>`, which is required by `Pin<Box<dyn futures::Future<Output = ()>>>: std::marker::Send`
     = note: required for `Unique<dyn futures::Future<Output = ()>>` to implement `std::marker::Send`
note: required because it appears within the type `Box<dyn futures::Future<Output = ()>>`
```

### Expected Behavior

Should compile.

I saw some special handling on wasm + Send bound, but I have not fully understand why we need them yet. 

### Additional Context

_No response_

### Are you willing to submit a PR to fix this bug?

- [ ] Yes, I would like to submit a PR.


Discussion / hints:

Fix patch:
diff --git a/integrations/object_store/Cargo.toml b/integrations/object_store/Cargo.toml
index 97e6e76bd510..2afc0abd0a07 100644
--- a/integrations/object_store/Cargo.toml
+++ b/integrations/object_store/Cargo.toml
@@ -37,7 +37,7 @@ flagset = "0.4"
 futures = "0.3"
 futures-util = "0.3"
 object_store = "0.11"
-opendal = { version = "0.51.0", path = "../../core" }
+opendal = { version = "0.51.0", path = "../../core", default-features = false }
 pin-project = "1.1"
 send_wrapper = { version = "0.6", features = ["futures"], optional = true }
 tokio = { version = "1", default-features = false }
diff --git a/integrations/object_store/README.md b/integrations/object_store/README.md
index 1250a0a4aabc..115488f3b8b2 100644
--- a/integrations/object_store/README.md
+++ b/integrations/object_store/README.md
@@ -78,6 +78,14 @@ async fn main() {
 }
 ```
 
+## WASM support
+
+To build with `wasm32-unknown-unknown` target, you need to enable the `send_wrapper` feature:
+
+```sh
+cargo build --target wasm32-unknown-unknown --features send_wrapper
+```
+
 ## Branding
 
 The first and most prominent mentions must use the full form: **Apache OpenDAL™** of the name for any individual usage (webpage, handout, slides, etc.) Depending on the context and writing style, you should use the full form of the name sufficiently often to ensure that readers clearly understand the association of both the OpenDAL project and the OpenDAL software product to the ASF as the parent organization.
diff --git a/integrations/object_store/src/lib.rs b/integrations/object_store/src/lib.rs
index 2afe685eb89e..f9951b8ce901 100644
--- a/integrations/object_store/src/lib.rs
+++ b/integrations/object_store/src/lib.rs
@@ -66,20 +66,21 @@ pub use store::OpendalStore;
 mod utils;
 
 // Make sure `send_wrapper` works as expected
-#[cfg(all(feature = "send_wrapper", target_arch = "wasm32"))]
+#[cfg(all(feature = "send_wrapper", test))]
 mod assert_send {
-    use object_store::ObjectStore;
+    use object_store::{ObjectStore, PutPayload};
+    use opendal::Operator;
 
     #[allow(dead_code)]
     fn assert_send<T: Send>(_: T) {}
 
     #[allow(dead_code)]
     fn assertion() {
-        let op = super::Operator::new(opendal::services::Memory::default())
+        let op = Operator::new(opendal::services::Memory::default())
             .unwrap()
             .finish();
         let store = super::OpendalStore::new(op);
-        assert_send(store.put(&"test".into(), bytes::Bytes::new()));
+        assert_send(store.put(&"test".into(), PutPayload::new()));
         assert_send(store.get(&"test".into()));
         assert_send(store.get_range(&"test".into(), 0..1));
         assert_send(store.head(&"test".into()));
diff --git a/integrations/object_store/src/store.rs b/integrations/object_store/src/store.rs
index 32ccbc2d8a23..9ee32889f1ed 100644
--- a/integrations/object_store/src/store.rs
+++ b/integrations/object_store/src/store.rs
@@ -217,6 +217,7 @@ impl ObjectStore for OpendalStore {
 
         let stream = r
             .into_bytes_stream(0..meta.size as u64)
+            .into_send()
             .await
             .map_err(|err| object_store::Error::Generic {
                 store: "IoError",
@@ -400,6 +401,7 @@ impl ObjectStore for OpendalStore {
                 let meta = self
                     .inner
                     .stat(entry.path())
+                    .into_send()
                     .await
                     .map_err(|err| format_object_store_error(err, entry.path()))?;
                 objects.push(format_object_meta(entry.path(), &meta));


Test patch: