diff --git a/atrium-api/src/agent.rs b/atrium-api/src/agent.rs index f424a061..298284e4 100644 --- a/atrium-api/src/agent.rs +++ b/atrium-api/src/agent.rs @@ -168,7 +168,6 @@ mod tests { use crate::com::atproto::server::create_session::OutputData; use crate::did_doc::{DidDocument, Service, VerificationMethod}; use crate::types::TryIntoUnknown; - use async_trait::async_trait; use atrium_xrpc::HttpClient; use http::{HeaderMap, HeaderName, HeaderValue, Request, Response}; use std::collections::HashMap; @@ -189,8 +188,6 @@ mod tests { headers: Arc>>>, } - #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl HttpClient for MockClient { async fn send_http( &self, diff --git a/atrium-api/src/agent/inner.rs b/atrium-api/src/agent/inner.rs index 910924aa..2c7ee72e 100644 --- a/atrium-api/src/agent/inner.rs +++ b/atrium-api/src/agent/inner.rs @@ -2,7 +2,6 @@ use super::{Session, SessionStore}; use crate::did_doc::DidDocument; use crate::types::string::Did; use crate::types::TryFromUnknown; -use async_trait::async_trait; use atrium_xrpc::error::{Error, Result, XrpcErrorKind}; use atrium_xrpc::{HttpClient, OutputDataOrBytes, XrpcClient, XrpcRequest}; use http::{Method, Request, Response, Uri}; @@ -51,8 +50,6 @@ impl Clone for WrapperClient { } } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl HttpClient for WrapperClient where S: Send + Sync, @@ -67,8 +64,6 @@ where } } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl XrpcClient for WrapperClient where S: SessionStore + Send + Sync, @@ -231,8 +226,6 @@ where } } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl HttpClient for Client where S: Send + Sync, @@ -247,8 +240,6 @@ where } } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl XrpcClient for Client where S: SessionStore + Send + Sync, @@ -321,8 +312,6 @@ impl Store { } } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl SessionStore for Store where S: SessionStore + Send + Sync, diff --git a/atrium-api/src/agent/store.rs b/atrium-api/src/agent/store.rs index 3d2b3397..b79a5aef 100644 --- a/atrium-api/src/agent/store.rs +++ b/atrium-api/src/agent/store.rs @@ -1,16 +1,15 @@ mod memory; +use std::future::Future; + pub use self::memory::MemorySessionStore; pub(crate) use super::Session; -use async_trait::async_trait; -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] pub trait SessionStore { #[must_use] - async fn get_session(&self) -> Option; + fn get_session(&self) -> impl Future> + Send; #[must_use] - async fn set_session(&self, session: Session); + fn set_session(&self, session: Session) -> impl Future + Send; #[must_use] - async fn clear_session(&self); + fn clear_session(&self) -> impl Future + Send; } diff --git a/atrium-api/src/agent/store/memory.rs b/atrium-api/src/agent/store/memory.rs index d2933495..05eedaaf 100644 --- a/atrium-api/src/agent/store/memory.rs +++ b/atrium-api/src/agent/store/memory.rs @@ -1,5 +1,4 @@ use super::{Session, SessionStore}; -use async_trait::async_trait; use std::sync::Arc; use tokio::sync::RwLock; @@ -8,8 +7,6 @@ pub struct MemorySessionStore { session: Arc>>, } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl SessionStore for MemorySessionStore { async fn get_session(&self) -> Option { self.session.read().await.clone() diff --git a/atrium-xrpc-client/src/isahc.rs b/atrium-xrpc-client/src/isahc.rs index 6c3a0e51..41cfcebe 100644 --- a/atrium-xrpc-client/src/isahc.rs +++ b/atrium-xrpc-client/src/isahc.rs @@ -1,5 +1,4 @@ #![doc = "XrpcClient implementation for [isahc]"] -use async_trait::async_trait; use atrium_xrpc::http::{Request, Response}; use atrium_xrpc::{HttpClient, XrpcClient}; use isahc::{AsyncReadResponseExt, HttpClient as Client}; @@ -52,7 +51,6 @@ impl IsahcClientBuilder { } } -#[async_trait] impl HttpClient for IsahcClient { async fn send_http( &self, diff --git a/atrium-xrpc-client/src/reqwest.rs b/atrium-xrpc-client/src/reqwest.rs index 75aed6a2..4e42a52b 100644 --- a/atrium-xrpc-client/src/reqwest.rs +++ b/atrium-xrpc-client/src/reqwest.rs @@ -1,5 +1,4 @@ #![doc = "XrpcClient implementation for [reqwest]"] -use async_trait::async_trait; use atrium_xrpc::http::{Request, Response}; use atrium_xrpc::{HttpClient, XrpcClient}; use reqwest::Client; @@ -48,8 +47,6 @@ impl ReqwestClientBuilder { } } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl HttpClient for ReqwestClient { async fn send_http( &self, diff --git a/atrium-xrpc/src/lib.rs b/atrium-xrpc/src/lib.rs index e90327be..884e3dc3 100644 --- a/atrium-xrpc/src/lib.rs +++ b/atrium-xrpc/src/lib.rs @@ -13,7 +13,6 @@ mod tests { use super::*; use crate::error::{XrpcError, XrpcErrorKind}; use crate::{HttpClient, XrpcClient}; - use async_trait::async_trait; use http::{Request, Response}; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -24,8 +23,6 @@ mod tests { body: Vec, } - #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl HttpClient for DummyClient { async fn send_http( &self, diff --git a/atrium-xrpc/src/traits.rs b/atrium-xrpc/src/traits.rs index 1ece8c9b..4726aa58 100644 --- a/atrium-xrpc/src/traits.rs +++ b/atrium-xrpc/src/traits.rs @@ -2,20 +2,18 @@ use crate::error::Error; use crate::error::{XrpcError, XrpcErrorKind}; use crate::types::{Header, NSID_REFRESH_SESSION}; use crate::{InputDataOrBytes, OutputDataOrBytes, XrpcRequest}; -use async_trait::async_trait; use http::{Method, Request, Response}; use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; +use std::future::Future; /// An abstract HTTP client. -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] pub trait HttpClient { /// Send an HTTP request and return the response. - async fn send_http( + fn send_http( &self, request: Request>, - ) -> core::result::Result>, Box>; + ) -> impl Future>, Box>> + Send; } type XrpcResult = core::result::Result, self::Error>; @@ -24,87 +22,88 @@ type XrpcResult = core::result::Result, self::Error String; /// Get the authentication token to use `Authorization` header. #[allow(unused_variables)] - async fn authentication_token(&self, is_refresh: bool) -> Option { - None + fn authentication_token(&self, is_refresh: bool) -> impl Future> + Send { + async { None } } /// Get the `atproto-proxy` header. - async fn atproto_proxy_header(&self) -> Option { - None + fn atproto_proxy_header(&self) -> impl Future> + Send { + async { None } } /// Get the `atproto-accept-labelers` header. - async fn atproto_accept_labelers_header(&self) -> Option> { - None + fn atproto_accept_labelers_header(&self) -> impl Future>> + Send { + async { None } } /// Send an XRPC request and return the response. - async fn send_xrpc(&self, request: &XrpcRequest) -> XrpcResult + fn send_xrpc(&self, request: &XrpcRequest) -> impl Future> + Send where P: Serialize + Send + Sync, I: Serialize + Send + Sync, O: DeserializeOwned + Send + Sync, E: DeserializeOwned + Send + Sync + Debug, + Self: Sync, { - let mut uri = format!("{}/xrpc/{}", self.base_uri(), request.nsid); - // Query parameters - if let Some(p) = &request.parameters { - serde_html_form::to_string(p).map(|qs| { - uri += "?"; - uri += &qs; - })?; - }; - let mut builder = Request::builder().method(&request.method).uri(&uri); - // Headers - if let Some(encoding) = &request.encoding { - builder = builder.header(Header::ContentType, encoding); - } - if let Some(token) = self - .authentication_token( - request.method == Method::POST && request.nsid == NSID_REFRESH_SESSION, - ) - .await - { - builder = builder.header(Header::Authorization, format!("Bearer {}", token)); - } - if let Some(proxy) = self.atproto_proxy_header().await { - builder = builder.header(Header::AtprotoProxy, proxy); - } - if let Some(accept_labelers) = self.atproto_accept_labelers_header().await { - builder = builder.header(Header::AtprotoAcceptLabelers, accept_labelers.join(", ")); - } - // Body - let body = if let Some(input) = &request.input { - match input { - InputDataOrBytes::Data(data) => serde_json::to_vec(&data)?, - InputDataOrBytes::Bytes(bytes) => bytes.clone(), + async { + let mut uri = format!("{}/xrpc/{}", self.base_uri(), request.nsid); + // Query parameters + if let Some(p) = &request.parameters { + serde_html_form::to_string(p).map(|qs| { + uri += "?"; + uri += &qs; + })?; + }; + let mut builder = Request::builder().method(&request.method).uri(&uri); + // Headers + if let Some(encoding) = &request.encoding { + builder = builder.header(Header::ContentType, encoding); } - } else { - Vec::new() - }; - // Send - let (parts, body) = - self.send_http(builder.body(body)?).await.map_err(Error::HttpClient)?.into_parts(); - if parts.status.is_success() { - if parts - .headers - .get(http::header::CONTENT_TYPE) - .and_then(|value| value.to_str().ok()) - .map_or(false, |content_type| content_type.starts_with("application/json")) + if let Some(token) = self + .authentication_token( + request.method == Method::POST && request.nsid == NSID_REFRESH_SESSION, + ) + .await { - Ok(OutputDataOrBytes::Data(serde_json::from_slice(&body)?)) + builder = builder.header(Header::Authorization, format!("Bearer {}", token)); + } + if let Some(proxy) = self.atproto_proxy_header().await { + builder = builder.header(Header::AtprotoProxy, proxy); + } + if let Some(accept_labelers) = self.atproto_accept_labelers_header().await { + builder = builder.header(Header::AtprotoAcceptLabelers, accept_labelers.join(", ")); + } + // Body + let body = if let Some(input) = &request.input { + match input { + InputDataOrBytes::Data(data) => serde_json::to_vec(&data)?, + InputDataOrBytes::Bytes(bytes) => bytes.clone(), + } + } else { + Vec::new() + }; + // Send + let (parts, body) = + self.send_http(builder.body(body)?).await.map_err(Error::HttpClient)?.into_parts(); + if parts.status.is_success() { + if parts + .headers + .get(http::header::CONTENT_TYPE) + .and_then(|value| value.to_str().ok()) + .map_or(false, |content_type| content_type.starts_with("application/json")) + { + Ok(OutputDataOrBytes::Data(serde_json::from_slice(&body)?)) + } else { + Ok(OutputDataOrBytes::Bytes(body)) + } } else { - Ok(OutputDataOrBytes::Bytes(body)) + Err(Error::XrpcResponse(XrpcError { + status: parts.status, + error: serde_json::from_slice::>(&body).ok(), + })) } - } else { - Err(Error::XrpcResponse(XrpcError { - status: parts.status, - error: serde_json::from_slice::>(&body).ok(), - })) } } } diff --git a/bsky-sdk/src/agent.rs b/bsky-sdk/src/agent.rs index f8664e44..e7030ddd 100644 --- a/bsky-sdk/src/agent.rs +++ b/bsky-sdk/src/agent.rs @@ -260,13 +260,11 @@ where #[cfg(test)] mod tests { use super::*; - use async_trait::async_trait; use atrium_api::agent::Session; #[derive(Clone)] struct NoopStore; - #[async_trait] impl SessionStore for NoopStore { async fn get_session(&self) -> Option { unimplemented!() diff --git a/bsky-sdk/src/agent/builder.rs b/bsky-sdk/src/agent/builder.rs index fa7af946..9e333181 100644 --- a/bsky-sdk/src/agent/builder.rs +++ b/bsky-sdk/src/agent/builder.rs @@ -103,7 +103,6 @@ impl Default for BskyAgentBuilder { #[cfg(test)] mod tests { use super::*; - use async_trait::async_trait; use atrium_api::agent::Session; use atrium_api::com::atproto::server::create_session::OutputData; @@ -125,7 +124,6 @@ mod tests { struct MockSessionStore; - #[async_trait] impl SessionStore for MockSessionStore { async fn get_session(&self) -> Option { Some(session()) diff --git a/bsky-sdk/src/agent/config.rs b/bsky-sdk/src/agent/config.rs index a118ae99..85454ac3 100644 --- a/bsky-sdk/src/agent/config.rs +++ b/bsky-sdk/src/agent/config.rs @@ -1,8 +1,9 @@ //! Configuration for the [`BskyAgent`](super::BskyAgent). mod file; +use std::future::Future; + use crate::error::{Error, Result}; -use async_trait::async_trait; use atrium_api::agent::Session; pub use file::FileStore; use serde::{Deserialize, Serialize}; @@ -46,20 +47,18 @@ impl Default for Config { } /// The trait for loading configuration data. -#[async_trait] pub trait Loader { /// Loads the configuration data. - async fn load( + fn load( &self, - ) -> core::result::Result>; + ) -> impl Future>> + Send; } /// The trait for saving configuration data. -#[async_trait] pub trait Saver { /// Saves the configuration data. - async fn save( + fn save( &self, config: &Config, - ) -> core::result::Result<(), Box>; + ) -> impl Future>> + Send; } diff --git a/bsky-sdk/src/agent/config/file.rs b/bsky-sdk/src/agent/config/file.rs index 725cc55c..eb547d28 100644 --- a/bsky-sdk/src/agent/config/file.rs +++ b/bsky-sdk/src/agent/config/file.rs @@ -1,6 +1,5 @@ use super::{Config, Loader, Saver}; use anyhow::anyhow; -use async_trait::async_trait; use std::path::{Path, PathBuf}; /// An implementation of [`Loader`] and [`Saver`] that reads and writes a configuration file. @@ -19,7 +18,6 @@ impl FileStore { } } -#[async_trait] impl Loader for FileStore { async fn load( &self, @@ -33,7 +31,6 @@ impl Loader for FileStore { } } -#[async_trait] impl Saver for FileStore { async fn save( &self, diff --git a/bsky-sdk/src/lib.rs b/bsky-sdk/src/lib.rs index 948ccbd7..583a87d1 100644 --- a/bsky-sdk/src/lib.rs +++ b/bsky-sdk/src/lib.rs @@ -15,7 +15,6 @@ pub use error::{Error, Result}; #[cfg(test)] mod tests { - use async_trait::async_trait; use atrium_api::xrpc::http::{Request, Response}; use atrium_api::xrpc::types::Header; use atrium_api::xrpc::{HttpClient, XrpcClient}; @@ -24,7 +23,6 @@ mod tests { pub struct MockClient; - #[async_trait] impl HttpClient for MockClient { async fn send_http( &self, @@ -44,7 +42,6 @@ mod tests { } } - #[async_trait] impl XrpcClient for MockClient { fn base_uri(&self) -> String { String::new() diff --git a/bsky-sdk/src/record.rs b/bsky-sdk/src/record.rs index 9b61c70a..3688b83b 100644 --- a/bsky-sdk/src/record.rs +++ b/bsky-sdk/src/record.rs @@ -1,9 +1,10 @@ //! Record operations. mod agent; +use std::future::Future; + use crate::error::{Error, Result}; use crate::BskyAgent; -use async_trait::async_trait; use atrium_api::agent::store::SessionStore; use atrium_api::com::atproto::repo::{ create_record, delete_record, get_record, list_records, put_record, @@ -11,28 +12,24 @@ use atrium_api::com::atproto::repo::{ use atrium_api::types::{Collection, LimitedNonZeroU8, TryIntoUnknown}; use atrium_api::xrpc::XrpcClient; -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] pub trait Record where T: XrpcClient + Send + Sync, S: SessionStore + Send + Sync, { - async fn list( + fn list( agent: &BskyAgent, cursor: Option, limit: Option>, - ) -> Result; - async fn get(agent: &BskyAgent, rkey: String) -> Result; - async fn put(self, agent: &BskyAgent, rkey: String) -> Result; - async fn create(self, agent: &BskyAgent) -> Result; - async fn delete(agent: &BskyAgent, rkey: String) -> Result; + ) -> impl Future> + Send; + fn get(agent: &BskyAgent, rkey: String) -> impl Future> + Send; + fn put(self, agent: &BskyAgent, rkey: String) -> impl Future> + Send; + fn create(self, agent: &BskyAgent) -> impl Future> + Send; + fn delete(agent: &BskyAgent, rkey: String) -> impl Future> + Send; } macro_rules! record_impl { ($collection:path, $record:path, $record_data:path) => { - #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl Record for $record where T: XrpcClient + Send + Sync, @@ -150,8 +147,6 @@ macro_rules! record_impl { } } - #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl Record for $record_data where T: XrpcClient + Send + Sync, @@ -277,7 +272,6 @@ mod tests { struct MockClient; - #[async_trait] impl HttpClient for MockClient { async fn send_http( &self, @@ -307,7 +301,6 @@ mod tests { } } - #[async_trait] impl XrpcClient for MockClient { fn base_uri(&self) -> String { String::new() @@ -316,7 +309,6 @@ mod tests { struct MockSessionStore; - #[async_trait] impl SessionStore for MockSessionStore { async fn get_session(&self) -> Option { Some(