Refactor the Connection trait and Surreal methods (#1860)

This commit is contained in:
Rushmore Mushambi 2023-04-25 16:22:34 +02:00 committed by GitHub
parent 66b105dac0
commit e6b97ff8ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 306 additions and 534 deletions

View file

@ -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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<Response>> + Send + Sync + '_>>;
) -> Pin<Box<dyn Future<Output = Result<Response>> + 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>(

View file

@ -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<R>(
&mut self,
receiver: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<Response>> + Send + Sync + '_>> {
Box::pin(async move {
let response = receiver.into_recv_async().await?;
match response? {
DbResponse::Query(results) => Ok(results),
DbResponse::Other(..) => unreachable!(),
}
})
}
}

View file

@ -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<R>(
&mut self,
receiver: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<Response>> + Send + Sync + '_>> {
Box::pin(async move {
let response = receiver.into_recv_async().await?;
match response? {
DbResponse::Query(results) => Ok(results),
DbResponse::Other(..) => unreachable!(),
}
})
}
}

View file

@ -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

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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(

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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(

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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<Option<Route>>) {

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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<reqwest::Client> {

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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)]

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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(

View file

@ -28,38 +28,32 @@ pub struct Content<'r, C: Connection, D, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, C, D, R> Content<'r, C, D, R>
where
C: Connection,
D: Serialize,
{
fn split(self) -> Result<(&'r Router<C>, 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<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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
})
}
}

View file

@ -21,68 +21,79 @@ pub struct Create<'r, C: Connection, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, Client, R> Create<'r, Client, R>
where
Client: Connection,
{
async fn execute<T>(self) -> Result<T>
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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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<D>(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<R>);
create_methods!(Vec<R>);
impl<'r, C, R> Create<'r, C, Option<R>>
where
C: Connection,
{
/// Sets content of a record
pub fn content<D>(self, data: D) -> Content<'r, C, D, R>
where
D: Serialize,
{
content!(self, data)
}
}
impl<'r, C, R> Create<'r, C, Vec<R>>
where
C: Connection,
{
/// Sets content of a record
pub fn content<D>(self, data: D) -> Content<'r, C, D, R>
where
D: Serialize,
{
content!(self, data)
}
}

View file

@ -22,48 +22,47 @@ pub struct Delete<'r, C: Connection, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, Client, R> Delete<'r, Client, R>
where
Client: Connection,
{
async fn execute<T>(self) -> Result<T>
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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<Vec<R>>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + Sync + 'r>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.execute())
}
into_future! {}
}
impl<C, R> Delete<'_, C, Vec<R>>

View file

@ -25,38 +25,31 @@ pub struct Merge<'r, C: Connection, D, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, C, D, R> Merge<'r, C, D, R>
where
C: Connection,
D: Serialize,
{
fn split(self) -> Result<(&'r Router<C>, 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<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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
})
}
}

View file

@ -27,6 +27,38 @@ pub struct Patch<'r, C: Connection, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, Client, R> IntoFuture for Patch<'r, Client, R>
where
Client: Connection,
R: DeserializeOwned,
{
type Output = Result<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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
})
}
}

View file

@ -22,48 +22,47 @@ pub struct Select<'r, C: Connection, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, Client, R> Select<'r, Client, R>
where
Client: Connection,
{
async fn execute<T>(self) -> Result<T>
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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<Vec<R>>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + Sync + 'r>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.execute())
}
into_future! {}
}
impl<C, R> Select<'_, C, Vec<R>>

View file

@ -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<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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
})
}
}

View file

@ -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<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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
})
}
}

View file

@ -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<R>(
&mut self,
rx: Receiver<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<R>> + 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<Result<DbResponse>>,
) -> Pin<Box<dyn Future<Output = Result<QueryResponse>> + 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!(),
}
})
}
}

View file

@ -27,48 +27,47 @@ pub struct Update<'r, C: Connection, R> {
pub(super) response_type: PhantomData<R>,
}
impl<'r, Client, R> Update<'r, Client, R>
where
Client: Connection,
{
async fn execute<T>(self) -> Result<T>
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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<R>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 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<R>>
where
Client: Connection,
R: DeserializeOwned + Send + Sync + 'r,
R: DeserializeOwned,
{
type Output = Result<Vec<R>>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + Sync + 'r>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.execute())
}
into_future! {}
}
impl<C, R> Update<'_, C, Vec<R>>
@ -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<D>(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<D>(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>, R);
update_methods!(Vec<R>, Vec<R>);
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<R>>
where
C: Connection,
R: DeserializeOwned,
{
/// Replaces the current document / record data with the specified data
pub fn content<D>(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<D>(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<R>>
where
C: Connection,
R: DeserializeOwned,
{
/// Replaces the current document / record data with the specified data
pub fn content<D>(self, data: D) -> Content<'r, C, D, Vec<R>>
where
D: Serialize,
{
content!(self, data)
}
/// Merges the current document / record data with the specified data
pub fn merge<D>(self, data: D) -> Merge<'r, C, D, Vec<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, Vec<R>> {
patch!(self, patch)
}
}