use crate::api::conn::Method; use crate::api::conn::Param; use crate::api::conn::Router; use crate::api::opt::PatchOp; use crate::api::opt::Range; use crate::api::opt::Resource; use crate::api::Connection; use crate::api::Result; use crate::sql::Array; use crate::sql::Id; use crate::sql::Value; use serde::de::DeserializeOwned; use std::future::Future; use std::future::IntoFuture; use std::marker::PhantomData; use std::pin::Pin; use std::result::Result as StdResult; /// A patch future #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct Patch<'r, C: Connection, R> { pub(super) router: Result<&'r Router>, pub(super) resource: Result, pub(super) range: Option>, pub(super) patches: Vec>, pub(super) response_type: PhantomData, } macro_rules! into_future { ($method:ident) => { 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.$method(router?, Param::new(vec![param, patches])).await }) } }; } impl<'r, Client> IntoFuture for Patch<'r, Client, Value> where Client: Connection, { type Output = Result; type IntoFuture = Pin + Send + Sync + 'r>>; into_future! {execute_value} } impl<'r, Client, R> IntoFuture for Patch<'r, Client, Option> where Client: Connection, R: DeserializeOwned, { type Output = Result>; type IntoFuture = Pin + Send + Sync + 'r>>; into_future! {execute_opt} } impl<'r, Client, R> IntoFuture for Patch<'r, Client, Vec> where Client: Connection, R: DeserializeOwned, { type Output = Result>; type IntoFuture = Pin + Send + Sync + 'r>>; into_future! {execute_vec} } impl<'r, C, R> Patch<'r, C, R> where C: Connection, { /// Applies JSON Patch changes to all records, or a specific record, in the database. pub fn patch(mut self, PatchOp(patch): PatchOp) -> Patch<'r, C, R> { self.patches.push(patch); self } }