From e6b97ff8ff0760a7897366a21aba36fae15be35e Mon Sep 17 00:00:00 2001 From: Rushmore Mushambi Date: Tue, 25 Apr 2023 16:22:34 +0200 Subject: [PATCH] Refactor the `Connection` trait and `Surreal` methods (#1860) --- lib/src/api/conn.rs | 22 ++- lib/src/api/engine/any/native.rs | 32 ---- lib/src/api/engine/any/wasm.rs | 32 ---- lib/src/api/engine/local/mod.rs | 1 + lib/src/api/engine/local/native.rs | 32 ---- lib/src/api/engine/local/wasm.rs | 35 ----- lib/src/api/engine/remote/http/native.rs | 35 ----- lib/src/api/engine/remote/http/wasm.rs | 34 ----- lib/src/api/engine/remote/ws/native.rs | 32 ---- lib/src/api/engine/remote/ws/wasm.rs | 32 ---- lib/src/api/method/content.rs | 36 ++--- lib/src/api/method/create.rs | 93 +++++++----- lib/src/api/method/delete.rs | 47 +++--- lib/src/api/method/merge.rs | 37 ++--- lib/src/api/method/patch.rs | 58 ++++---- lib/src/api/method/select.rs | 47 +++--- lib/src/api/method/signin.rs | 11 +- lib/src/api/method/signup.rs | 11 +- lib/src/api/method/tests/protocol.rs | 32 ---- lib/src/api/method/update.rs | 181 ++++++++++++++--------- 20 files changed, 306 insertions(+), 534 deletions(-) diff --git a/lib/src/api/conn.rs b/lib/src/api/conn.rs index f42abf54..a47fb132 100644 --- a/lib/src/api/conn.rs +++ b/lib/src/api/conn.rs @@ -4,6 +4,7 @@ use crate::api::opt::Endpoint; use crate::api::ExtraFeatures; use crate::api::Result; use crate::api::Surreal; +use crate::opt::from_value; use crate::sql::Query; use crate::sql::Value; use flume::Receiver; @@ -174,13 +175,30 @@ pub trait Connection: Sized + Send + Sync + 'static { receiver: Receiver>, ) -> Pin> + Send + Sync + '_>> where - R: DeserializeOwned; + R: DeserializeOwned, + { + Box::pin(async move { + let response = receiver.into_recv_async().await?; + match response? { + DbResponse::Other(value) => from_value(value).map_err(Into::into), + DbResponse::Query(..) => unreachable!(), + } + }) + } /// Receive the response of the `query` method fn recv_query( &mut self, receiver: Receiver>, - ) -> Pin> + Send + Sync + '_>>; + ) -> Pin> + Send + Sync + '_>> { + Box::pin(async move { + let response = receiver.into_recv_async().await?; + match response? { + DbResponse::Query(results) => Ok(results), + DbResponse::Other(..) => unreachable!(), + } + }) + } /// Execute all methods except `query` fn execute<'r, R>( diff --git a/lib/src/api/engine/any/native.rs b/lib/src/api/engine/any/native.rs index f31d41f1..726a10a2 100644 --- a/lib/src/api/engine/any/native.rs +++ b/lib/src/api/engine/any/native.rs @@ -9,7 +9,6 @@ use crate::api::engine::any::Any; #[cfg(feature = "protocol-http")] use crate::api::engine::remote::http; use crate::api::err::Error; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; #[cfg(any(feature = "native-tls", feature = "rustls"))] #[cfg(feature = "protocol-http")] @@ -17,7 +16,6 @@ use crate::api::opt::Tls; use crate::api::DbResponse; #[allow(unused_imports)] // used by the DB engines use crate::api::ExtraFeatures; -use crate::api::Response; use crate::api::Result; use crate::api::Surreal; use crate::error::Db as DbError; @@ -25,7 +23,6 @@ use flume::Receiver; use once_cell::sync::OnceCell; #[cfg(feature = "protocol-http")] use reqwest::ClientBuilder; -use serde::de::DeserializeOwned; use std::collections::HashSet; use std::future::Future; use std::marker::PhantomData; @@ -226,33 +223,4 @@ impl Connection for Any { Ok(receiver) }) } - - fn recv( - &mut self, - receiver: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = receiver.into_recv_async().await?; - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - receiver: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = receiver.into_recv_async().await?; - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } diff --git a/lib/src/api/engine/any/wasm.rs b/lib/src/api/engine/any/wasm.rs index 6d9ca69b..7d6a3106 100644 --- a/lib/src/api/engine/any/wasm.rs +++ b/lib/src/api/engine/any/wasm.rs @@ -7,18 +7,15 @@ use crate::api::conn::Router; use crate::api::engine; use crate::api::engine::any::Any; use crate::api::err::Error; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; use crate::api::DbResponse; #[allow(unused_imports)] // used by the `ws` and `http` protocols use crate::api::ExtraFeatures; -use crate::api::Response; use crate::api::Result; use crate::api::Surreal; use crate::error::Db as DbError; use flume::Receiver; use once_cell::sync::OnceCell; -use serde::de::DeserializeOwned; use std::collections::HashSet; use std::future::Future; use std::marker::PhantomData; @@ -192,33 +189,4 @@ impl Connection for Any { Ok(receiver) }) } - - fn recv( - &mut self, - receiver: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = receiver.into_recv_async().await?; - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - receiver: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = receiver.into_recv_async().await?; - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } diff --git a/lib/src/api/engine/local/mod.rs b/lib/src/api/engine/local/mod.rs index 95914f95..d47c0666 100644 --- a/lib/src/api/engine/local/mod.rs +++ b/lib/src/api/engine/local/mod.rs @@ -70,6 +70,7 @@ use tokio::io::AsyncWrite; #[cfg(not(target_arch = "wasm32"))] use tokio::io::AsyncWriteExt; +#[cfg(not(target_arch = "wasm32"))] const LOG: &str = "surrealdb::api::engine::local"; /// In-memory database diff --git a/lib/src/api/engine/local/native.rs b/lib/src/api/engine/local/native.rs index 950c52ec..b227e7a9 100644 --- a/lib/src/api/engine/local/native.rs +++ b/lib/src/api/engine/local/native.rs @@ -5,10 +5,8 @@ use crate::api::conn::Param; use crate::api::conn::Route; use crate::api::conn::Router; use crate::api::engine::local::Db; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; use crate::api::ExtraFeatures; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use crate::dbs::Session; @@ -17,7 +15,6 @@ use flume::Receiver; use flume::Sender; use futures::StreamExt; use once_cell::sync::OnceCell; -use serde::de::DeserializeOwned; use std::collections::BTreeMap; use std::collections::HashSet; use std::future::Future; @@ -80,35 +77,6 @@ impl Connection for Db { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = rx.into_recv_async().await?; - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = rx.into_recv_async().await?; - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } pub(crate) fn router( diff --git a/lib/src/api/engine/local/wasm.rs b/lib/src/api/engine/local/wasm.rs index 1264b459..2cfd975f 100644 --- a/lib/src/api/engine/local/wasm.rs +++ b/lib/src/api/engine/local/wasm.rs @@ -1,4 +1,3 @@ -use super::LOG; use crate::api::conn::Connection; use crate::api::conn::DbResponse; use crate::api::conn::Method; @@ -6,9 +5,7 @@ use crate::api::conn::Param; use crate::api::conn::Route; use crate::api::conn::Router; use crate::api::engine::local::Db; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use crate::dbs::Session; @@ -17,7 +14,6 @@ use flume::Receiver; use flume::Sender; use futures::StreamExt; use once_cell::sync::OnceCell; -use serde::de::DeserializeOwned; use std::collections::BTreeMap; use std::collections::HashSet; use std::future::Future; @@ -80,37 +76,6 @@ impl Connection for Db { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = rx.into_recv_async().await?; - trace!(target: LOG, "Response {response:?}"); - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = rx.into_recv_async().await?; - trace!(target: LOG, "Response {response:?}"); - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } pub(crate) fn router( diff --git a/lib/src/api/engine/remote/http/native.rs b/lib/src/api/engine/remote/http/native.rs index 5d22d038..a6dc7632 100644 --- a/lib/src/api/engine/remote/http/native.rs +++ b/lib/src/api/engine/remote/http/native.rs @@ -1,17 +1,14 @@ use super::Client; -use super::LOG; use crate::api::conn::Connection; use crate::api::conn::DbResponse; use crate::api::conn::Method; use crate::api::conn::Param; use crate::api::conn::Route; use crate::api::conn::Router; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; #[cfg(any(feature = "native-tls", feature = "rustls"))] use crate::api::opt::Tls; use crate::api::ExtraFeatures; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use flume::Receiver; @@ -20,7 +17,6 @@ use indexmap::IndexMap; use once_cell::sync::OnceCell; use reqwest::header::HeaderMap; use reqwest::ClientBuilder; -use serde::de::DeserializeOwned; use std::collections::HashSet; use std::future::Future; use std::marker::PhantomData; @@ -101,37 +97,6 @@ impl Connection for Client { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = rx.into_recv_async().await?; - trace!(target: LOG, "Response {response:?}"); - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = rx.into_recv_async().await?; - trace!(target: LOG, "Response {response:?}"); - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } pub(crate) fn router(base_url: Url, client: reqwest::Client, route_rx: Receiver>) { diff --git a/lib/src/api/engine/remote/http/wasm.rs b/lib/src/api/engine/remote/http/wasm.rs index 35d3e6b4..26f41622 100644 --- a/lib/src/api/engine/remote/http/wasm.rs +++ b/lib/src/api/engine/remote/http/wasm.rs @@ -6,10 +6,8 @@ use crate::api::conn::Method; use crate::api::conn::Param; use crate::api::conn::Route; use crate::api::conn::Router; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; use crate::api::ExtraFeatures; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use flume::Receiver; @@ -19,7 +17,6 @@ use indexmap::IndexMap; use once_cell::sync::OnceCell; use reqwest::header::HeaderMap; use reqwest::ClientBuilder; -use serde::de::DeserializeOwned; use std::collections::HashSet; use std::future::Future; use std::marker::PhantomData; @@ -86,37 +83,6 @@ impl Connection for Client { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = rx.into_recv_async().await?; - trace!(target: LOG, "Response {response:?}"); - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = rx.into_recv_async().await?; - trace!(target: LOG, "Response {response:?}"); - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } async fn client(base_url: &Url) -> Result { diff --git a/lib/src/api/engine/remote/ws/native.rs b/lib/src/api/engine/remote/ws/native.rs index 5c7cb58a..8e27d010 100644 --- a/lib/src/api/engine/remote/ws/native.rs +++ b/lib/src/api/engine/remote/ws/native.rs @@ -11,12 +11,10 @@ use crate::api::engine::remote::ws::Response; use crate::api::engine::remote::ws::PING_INTERVAL; use crate::api::engine::remote::ws::PING_METHOD; use crate::api::err::Error; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; #[cfg(any(feature = "native-tls", feature = "rustls"))] use crate::api::opt::Tls; use crate::api::ExtraFeatures; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use crate::engine::remote::ws::IntervalStream; @@ -29,7 +27,6 @@ use futures::StreamExt; use futures_concurrency::stream::Merge as _; use indexmap::IndexMap; use once_cell::sync::OnceCell; -use serde::de::DeserializeOwned; use std::borrow::BorrowMut; use std::collections::hash_map::Entry; use std::collections::BTreeMap; @@ -161,35 +158,6 @@ impl Connection for Client { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = rx.into_recv_async().await?; - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = rx.into_recv_async().await?; - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } #[allow(clippy::too_many_lines)] diff --git a/lib/src/api/engine/remote/ws/wasm.rs b/lib/src/api/engine/remote/ws/wasm.rs index 505f3a0a..59682841 100644 --- a/lib/src/api/engine/remote/ws/wasm.rs +++ b/lib/src/api/engine/remote/ws/wasm.rs @@ -11,10 +11,8 @@ use crate::api::engine::remote::ws::Response; use crate::api::engine::remote::ws::PING_INTERVAL; use crate::api::engine::remote::ws::PING_METHOD; use crate::api::err::Error; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; use crate::api::ExtraFeatures; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use crate::engine::remote::ws::IntervalStream; @@ -30,7 +28,6 @@ use once_cell::sync::OnceCell; use pharos::Channel; use pharos::Observable; use pharos::ObserveConfig; -use serde::de::DeserializeOwned; use std::collections::hash_map::Entry; use std::collections::BTreeMap; use std::collections::HashMap; @@ -116,35 +113,6 @@ impl Connection for Client { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let response = rx.into_recv_async().await?; - match response? { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let response = rx.into_recv_async().await?; - match response? { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } pub(crate) fn router( diff --git a/lib/src/api/method/content.rs b/lib/src/api/method/content.rs index 8b90d110..c8a55369 100644 --- a/lib/src/api/method/content.rs +++ b/lib/src/api/method/content.rs @@ -28,38 +28,32 @@ pub struct Content<'r, C: Connection, D, R> { pub(super) response_type: PhantomData, } -impl<'r, C, D, R> Content<'r, C, D, R> -where - C: Connection, - D: Serialize, -{ - fn split(self) -> Result<(&'r Router, Method, Param)> { - let resource = self.resource?; - let param = match self.range { - Some(range) => resource.with_range(range)?, - None => resource.into(), - }; - let content = to_value(self.content)?; - let param = Param::new(vec![param, content]); - Ok((self.router?, self.method, param)) - } -} - impl<'r, Client, D, R> IntoFuture for Content<'r, Client, D, R> where Client: Connection, D: Serialize, - R: DeserializeOwned + Send + Sync, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; fn into_future(self) -> Self::IntoFuture { - let result = self.split(); + let Content { + router, + method, + resource, + range, + content, + .. + } = self; + let content = to_value(content); Box::pin(async move { - let (router, method, param) = result?; + let param = match range { + Some(range) => resource?.with_range(range)?, + None => resource?.into(), + }; let mut conn = Client::new(method); - conn.execute(router, param).await + conn.execute(router?, Param::new(vec![param, content?])).await }) } } diff --git a/lib/src/api/method/create.rs b/lib/src/api/method/create.rs index 7899c7b4..5d27002b 100644 --- a/lib/src/api/method/create.rs +++ b/lib/src/api/method/create.rs @@ -21,68 +21,79 @@ pub struct Create<'r, C: Connection, R> { pub(super) response_type: PhantomData, } -impl<'r, Client, R> Create<'r, Client, R> -where - Client: Connection, -{ - async fn execute(self) -> Result - where - T: DeserializeOwned, - { - let mut conn = Client::new(Method::Create); - conn.execute(self.router?, Param::new(vec![self.resource?.into()])).await - } +macro_rules! into_future { + () => { + fn into_future(self) -> Self::IntoFuture { + let Create { + router, + resource, + .. + } = self; + Box::pin(async { + let mut conn = Client::new(Method::Create); + conn.execute(router?, Param::new(vec![resource?.into()])).await + }) + } + }; } impl<'r, Client, R> IntoFuture for Create<'r, Client, Option> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl<'r, Client, R> IntoFuture for Create<'r, Client, Vec> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } -macro_rules! create_methods { - ($this:ty) => { - impl<'r, C, R> Create<'r, C, $this> - where - C: Connection, - { - /// Sets content of a record - pub fn content(self, data: D) -> Content<'r, C, D, R> - where - D: Serialize, - { - Content { - router: self.router, - method: Method::Create, - resource: self.resource, - range: None, - content: data, - response_type: PhantomData, - } - } +macro_rules! content { + ($this:ident, $data:ident) => { + Content { + router: $this.router, + method: Method::Create, + resource: $this.resource, + range: None, + content: $data, + response_type: PhantomData, } }; } -create_methods!(Option); -create_methods!(Vec); +impl<'r, C, R> Create<'r, C, Option> +where + C: Connection, +{ + /// Sets content of a record + pub fn content(self, data: D) -> Content<'r, C, D, R> + where + D: Serialize, + { + content!(self, data) + } +} + +impl<'r, C, R> Create<'r, C, Vec> +where + C: Connection, +{ + /// Sets content of a record + pub fn content(self, data: D) -> Content<'r, C, D, R> + where + D: Serialize, + { + content!(self, data) + } +} diff --git a/lib/src/api/method/delete.rs b/lib/src/api/method/delete.rs index feddd9d0..e90b44a0 100644 --- a/lib/src/api/method/delete.rs +++ b/lib/src/api/method/delete.rs @@ -22,48 +22,47 @@ pub struct Delete<'r, C: Connection, R> { pub(super) response_type: PhantomData, } -impl<'r, Client, R> Delete<'r, Client, R> -where - Client: Connection, -{ - async fn execute(self) -> Result - where - T: DeserializeOwned, - { - let resource = self.resource?; - let param = match self.range { - Some(range) => resource.with_range(range)?, - None => resource.into(), - }; - let mut conn = Client::new(Method::Delete); - conn.execute(self.router?, Param::new(vec![param])).await - } +macro_rules! into_future { + () => { + fn into_future(self) -> Self::IntoFuture { + let Delete { + router, + resource, + range, + .. + } = self; + Box::pin(async { + let param = match range { + Some(range) => resource?.with_range(range)?, + None => resource?.into(), + }; + let mut conn = Client::new(Method::Delete); + conn.execute(router?, Param::new(vec![param])).await + }) + } + }; } impl<'r, Client, R> IntoFuture for Delete<'r, Client, Option> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl<'r, Client, R> IntoFuture for Delete<'r, Client, Vec> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result>; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl Delete<'_, C, Vec> diff --git a/lib/src/api/method/merge.rs b/lib/src/api/method/merge.rs index e857a7d5..d02b429a 100644 --- a/lib/src/api/method/merge.rs +++ b/lib/src/api/method/merge.rs @@ -25,38 +25,31 @@ pub struct Merge<'r, C: Connection, D, R> { pub(super) response_type: PhantomData, } -impl<'r, C, D, R> Merge<'r, C, D, R> -where - C: Connection, - D: Serialize, -{ - fn split(self) -> Result<(&'r Router, Method, Param)> { - let resource = self.resource?; - let param = match self.range { - Some(range) => resource.with_range(range)?, - None => resource.into(), - }; - let content = to_value(self.content)?; - let param = Param::new(vec![param, content]); - Ok((self.router?, Method::Merge, param)) - } -} - impl<'r, Client, D, R> IntoFuture for Merge<'r, Client, D, R> where Client: Connection, D: Serialize, - R: DeserializeOwned + Send + Sync, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; fn into_future(self) -> Self::IntoFuture { - let result = self.split(); + let Merge { + router, + resource, + range, + content, + .. + } = self; + let content = to_value(content); Box::pin(async move { - let (router, method, param) = result?; - let mut conn = Client::new(method); - conn.execute(router, param).await + let param = match range { + Some(range) => resource?.with_range(range)?, + None => resource?.into(), + }; + let mut conn = Client::new(Method::Merge); + conn.execute(router?, Param::new(vec![param, content?])).await }) } } diff --git a/lib/src/api/method/patch.rs b/lib/src/api/method/patch.rs index 1a7c8b4e..b9b34602 100644 --- a/lib/src/api/method/patch.rs +++ b/lib/src/api/method/patch.rs @@ -27,6 +27,38 @@ pub struct Patch<'r, C: Connection, R> { pub(super) response_type: PhantomData, } +impl<'r, Client, R> IntoFuture for Patch<'r, Client, R> +where + Client: Connection, + R: DeserializeOwned, +{ + type Output = Result; + type IntoFuture = Pin + Send + Sync + 'r>>; + + fn into_future(self) -> Self::IntoFuture { + let Patch { + router, + resource, + range, + patches, + .. + } = self; + Box::pin(async move { + let param = match range { + Some(range) => resource?.with_range(range)?, + None => resource?.into(), + }; + let mut vec = Vec::with_capacity(patches.len()); + for result in patches { + vec.push(result?); + } + let patches = Value::Array(Array(vec)); + let mut conn = Client::new(Method::Patch); + conn.execute(router?, Param::new(vec![param, patches])).await + }) + } +} + impl<'r, C, R> Patch<'r, C, R> where C: Connection, @@ -37,29 +69,3 @@ where self } } - -impl<'r, Client, R> IntoFuture for Patch<'r, Client, R> -where - Client: Connection, - R: DeserializeOwned + Send + Sync, -{ - type Output = Result; - type IntoFuture = Pin + Send + Sync + 'r>>; - - fn into_future(self) -> Self::IntoFuture { - Box::pin(async move { - let resource = self.resource?; - let param = match self.range { - Some(range) => resource.with_range(range)?, - None => resource.into(), - }; - let mut patches = Vec::with_capacity(self.patches.len()); - for result in self.patches { - patches.push(result?); - } - let patches = Value::Array(Array(patches)); - let mut conn = Client::new(Method::Patch); - conn.execute(self.router?, Param::new(vec![param, patches])).await - }) - } -} diff --git a/lib/src/api/method/select.rs b/lib/src/api/method/select.rs index 656eb5d0..dacc4f2e 100644 --- a/lib/src/api/method/select.rs +++ b/lib/src/api/method/select.rs @@ -22,48 +22,47 @@ pub struct Select<'r, C: Connection, R> { pub(super) response_type: PhantomData, } -impl<'r, Client, R> Select<'r, Client, R> -where - Client: Connection, -{ - async fn execute(self) -> Result - where - T: DeserializeOwned, - { - let resource = self.resource?; - let param = match self.range { - Some(range) => resource.with_range(range)?, - None => resource.into(), - }; - let mut conn = Client::new(Method::Select); - conn.execute(self.router?, Param::new(vec![param])).await - } +macro_rules! into_future { + () => { + fn into_future(self) -> Self::IntoFuture { + let Select { + router, + resource, + range, + .. + } = self; + Box::pin(async move { + let param = match range { + Some(range) => resource?.with_range(range)?, + None => resource?.into(), + }; + let mut conn = Client::new(Method::Select); + conn.execute(router?, Param::new(vec![param])).await + }) + } + }; } impl<'r, Client, R> IntoFuture for Select<'r, Client, Option> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl<'r, Client, R> IntoFuture for Select<'r, Client, Vec> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result>; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl Select<'_, C, Vec> diff --git a/lib/src/api/method/signin.rs b/lib/src/api/method/signin.rs index b99af53d..c830a5e5 100644 --- a/lib/src/api/method/signin.rs +++ b/lib/src/api/method/signin.rs @@ -24,19 +24,24 @@ pub struct Signin<'r, C: Connection, R> { impl<'r, Client, R> IntoFuture for Signin<'r, Client, R> where Client: Connection, - R: DeserializeOwned + Send + Sync, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; fn into_future(self) -> Self::IntoFuture { + let Signin { + router, + credentials, + .. + } = self; Box::pin(async move { - let router = self.router?; + let router = router?; if !router.features.contains(&ExtraFeatures::Auth) { return Err(Error::AuthNotSupported.into()); } let mut conn = Client::new(Method::Signin); - conn.execute(router, Param::new(vec![self.credentials?])).await + conn.execute(router, Param::new(vec![credentials?])).await }) } } diff --git a/lib/src/api/method/signup.rs b/lib/src/api/method/signup.rs index c6156871..c8774d91 100644 --- a/lib/src/api/method/signup.rs +++ b/lib/src/api/method/signup.rs @@ -24,19 +24,24 @@ pub struct Signup<'r, C: Connection, R> { impl<'r, Client, R> IntoFuture for Signup<'r, Client, R> where Client: Connection, - R: DeserializeOwned + Send + Sync, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; fn into_future(self) -> Self::IntoFuture { + let Signup { + router, + credentials, + .. + } = self; Box::pin(async move { - let router = self.router?; + let router = router?; if !router.features.contains(&ExtraFeatures::Auth) { return Err(Error::AuthNotSupported.into()); } let mut conn = Client::new(Method::Signup); - conn.execute(router, Param::new(vec![self.credentials?])).await + conn.execute(router, Param::new(vec![credentials?])).await }) } } diff --git a/lib/src/api/method/tests/protocol.rs b/lib/src/api/method/tests/protocol.rs index a79ace17..c7b81590 100644 --- a/lib/src/api/method/tests/protocol.rs +++ b/lib/src/api/method/tests/protocol.rs @@ -5,17 +5,14 @@ use crate::api::conn::Method; use crate::api::conn::Param; use crate::api::conn::Route; use crate::api::conn::Router; -use crate::api::opt::from_value; use crate::api::opt::Endpoint; use crate::api::opt::IntoEndpoint; use crate::api::Connect; use crate::api::ExtraFeatures; -use crate::api::Response as QueryResponse; use crate::api::Result; use crate::api::Surreal; use flume::Receiver; use once_cell::sync::OnceCell; -use serde::de::DeserializeOwned; use std::collections::HashSet; use std::future::Future; use std::marker::PhantomData; @@ -112,33 +109,4 @@ impl Connection for Client { Ok(receiver) }) } - - fn recv( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> - where - R: DeserializeOwned, - { - Box::pin(async move { - let result = rx.into_recv_async().await.unwrap(); - match result.unwrap() { - DbResponse::Other(value) => from_value(value).map_err(Into::into), - DbResponse::Query(..) => unreachable!(), - } - }) - } - - fn recv_query( - &mut self, - rx: Receiver>, - ) -> Pin> + Send + Sync + '_>> { - Box::pin(async move { - let result = rx.into_recv_async().await.unwrap(); - match result.unwrap() { - DbResponse::Query(results) => Ok(results), - DbResponse::Other(..) => unreachable!(), - } - }) - } } diff --git a/lib/src/api/method/update.rs b/lib/src/api/method/update.rs index 3e60741f..9fde5749 100644 --- a/lib/src/api/method/update.rs +++ b/lib/src/api/method/update.rs @@ -27,48 +27,47 @@ pub struct Update<'r, C: Connection, R> { pub(super) response_type: PhantomData, } -impl<'r, Client, R> Update<'r, Client, R> -where - Client: Connection, -{ - async fn execute(self) -> Result - where - T: DeserializeOwned, - { - let resource = self.resource?; - let param = match self.range { - Some(range) => resource.with_range(range)?, - None => resource.into(), - }; - let mut conn = Client::new(Method::Update); - conn.execute(self.router?, Param::new(vec![param])).await - } +macro_rules! into_future { + () => { + fn into_future(self) -> Self::IntoFuture { + let Update { + router, + resource, + range, + .. + } = self; + Box::pin(async move { + let param = match range { + Some(range) => resource?.with_range(range)?, + None => resource?.into(), + }; + let mut conn = Client::new(Method::Update); + conn.execute(router?, Param::new(vec![param])).await + }) + } + }; } impl<'r, Client, R> IntoFuture for Update<'r, Client, Option> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl<'r, Client, R> IntoFuture for Update<'r, Client, Vec> where Client: Connection, - R: DeserializeOwned + Send + Sync + 'r, + R: DeserializeOwned, { type Output = Result>; type IntoFuture = Pin + Send + Sync + 'r>>; - fn into_future(self) -> Self::IntoFuture { - Box::pin(self.execute()) - } + into_future! {} } impl Update<'_, C, Vec> @@ -82,55 +81,93 @@ where } } -macro_rules! update_methods { - ($this:ty, $res:ty) => { - impl<'r, C, R> Update<'r, C, $this> - where - C: Connection, - R: DeserializeOwned + Send + Sync, - { - /// Replaces the current document / record data with the specified data - pub fn content(self, data: D) -> Content<'r, C, D, $res> - where - D: Serialize, - { - Content { - router: self.router, - method: Method::Update, - resource: self.resource, - range: self.range, - content: data, - response_type: PhantomData, - } - } - - /// Merges the current document / record data with the specified data - pub fn merge(self, data: D) -> Merge<'r, C, D, $res> - where - D: Serialize, - { - Merge { - router: self.router, - resource: self.resource, - range: self.range, - content: data, - response_type: PhantomData, - } - } - - /// Patches the current document / record data with the specified JSON Patch data - pub fn patch(self, PatchOp(patch): PatchOp) -> Patch<'r, C, $res> { - Patch { - router: self.router, - resource: self.resource, - range: self.range, - patches: vec![patch], - response_type: PhantomData, - } - } +macro_rules! content { + ($this:ident, $data:ident) => { + Content { + router: $this.router, + method: Method::Update, + resource: $this.resource, + range: $this.range, + content: $data, + response_type: PhantomData, } }; } -update_methods!(Option, R); -update_methods!(Vec, Vec); +macro_rules! merge { + ($this:ident, $data:ident) => { + Merge { + router: $this.router, + resource: $this.resource, + range: $this.range, + content: $data, + response_type: PhantomData, + } + }; +} + +macro_rules! patch { + ($this:ident, $data:ident) => { + Patch { + router: $this.router, + resource: $this.resource, + range: $this.range, + patches: vec![$data], + response_type: PhantomData, + } + }; +} + +impl<'r, C, R> Update<'r, C, Option> +where + C: Connection, + R: DeserializeOwned, +{ + /// Replaces the current document / record data with the specified data + pub fn content(self, data: D) -> Content<'r, C, D, R> + where + D: Serialize, + { + content!(self, data) + } + + /// Merges the current document / record data with the specified data + pub fn merge(self, data: D) -> Merge<'r, C, D, R> + where + D: Serialize, + { + merge!(self, data) + } + + /// Patches the current document / record data with the specified JSON Patch data + pub fn patch(self, PatchOp(patch): PatchOp) -> Patch<'r, C, R> { + patch!(self, patch) + } +} + +impl<'r, C, R> Update<'r, C, Vec> +where + C: Connection, + R: DeserializeOwned, +{ + /// Replaces the current document / record data with the specified data + pub fn content(self, data: D) -> Content<'r, C, D, Vec> + where + D: Serialize, + { + content!(self, data) + } + + /// Merges the current document / record data with the specified data + pub fn merge(self, data: D) -> Merge<'r, C, D, Vec> + where + D: Serialize, + { + merge!(self, data) + } + + /// Patches the current document / record data with the specified JSON Patch data + pub fn patch(self, PatchOp(patch): PatchOp) -> Patch<'r, C, Vec> { + patch!(self, patch) + } +}