diff --git a/duper_rpc/src/de.rs b/duper_rpc/src/de.rs index 5c9ac18..a42d67c 100644 --- a/duper_rpc/src/de.rs +++ b/duper_rpc/src/de.rs @@ -1,7 +1,122 @@ use duper::DuperValue; use serde_core::{Deserialize, de::Visitor}; -use crate::{DuperRpcVersion, Error, Request, RequestCall, RequestId}; +use crate::{DuperRpcVersion, Error, Request, RequestCall, RequestId, Response, ResponseResult}; + +struct ErrorVisitor {} + +impl<'de> Visitor<'de> for ErrorVisitor { + type Value = Error; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a duper_rpc error") + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde_core::de::MapAccess<'de>, + { + let mut typ: Option = None; + let mut value: Option> = None; + + while let Some(key) = map.next_key::()? { + match key.as_ref() { + "type" => { + if typ.is_some() { + return Err(serde_core::de::Error::duplicate_field("type")); + } else { + typ = Some(map.next_value()?); + } + } + "value" => { + if value.is_some() { + return Err(serde_core::de::Error::duplicate_field("value")); + } else { + value = Some(map.next_value()?); + } + } + field => { + return Err(serde_core::de::Error::unknown_field( + field, + &["type", "value"], + )); + } + } + } + + let Some(typ) = typ else { + return Err(serde_core::de::Error::missing_field("type")); + }; + match typ.as_ref() { + "ParseError" => { + if value.is_some() { + return Err(serde_core::de::Error::custom( + "ParseError cannot have value", + )); + } + Ok(Error::ParseError) + } + "InvalidRequest" => { + if value.is_some() { + return Err(serde_core::de::Error::custom( + "InvalidRequest cannot have value", + )); + } + Ok(Error::InvalidRequest) + } + "MethodNotFound" => { + if value.is_some() { + return Err(serde_core::de::Error::custom( + "MethodNotFound cannot have value", + )); + } + Ok(Error::MethodNotFound) + } + "InvalidParams" => { + if value.is_some() { + return Err(serde_core::de::Error::custom( + "InvalidParams cannot have value", + )); + } + Ok(Error::InvalidParams) + } + "InternalError" => { + if value.is_some() { + return Err(serde_core::de::Error::custom( + "InternalError cannot have value", + )); + } + Ok(Error::InternalError) + } + "Custom" => { + let Some(value) = value else { + return Err(serde_core::de::Error::missing_field("value")); + }; + Ok(Error::Custom(value.static_clone())) + } + typ => Err(serde_core::de::Error::unknown_field( + typ, + &[ + "ParseError", + "InvalidRequest", + "MethodNotFound", + "InvalidParams", + "InternalError", + "Custom", + ], + )), + } + } +} + +impl<'de> Deserialize<'de> for Error { + fn deserialize(deserializer: D) -> Result + where + D: serde_core::Deserializer<'de>, + { + deserializer.deserialize_map(ErrorVisitor {}) + } +} struct RequestIdVisitor {} @@ -256,3 +371,136 @@ impl<'de> Deserialize<'de> for Request { })) } } + +struct ResponseResultVisitor {} + +impl<'de> Visitor<'de> for ResponseResultVisitor { + type Value = ResponseResult; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a single duper_rpc response result") + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde_core::de::MapAccess<'de>, + { + let mut duper_rpc: Option = None; + let mut id: Option = None; + let mut result: Option> = None; + let mut error: Option = None; + + while let Some(key) = map.next_key::()? { + match key.as_ref() { + "duper_rpc" => { + if duper_rpc.is_some() { + return Err(serde_core::de::Error::duplicate_field("duper_rpc")); + } else { + match map.next_value::()?.as_ref() { + "0.1" => duper_rpc = Some(DuperRpcVersion::DuperRpc01), + version => { + return Err(serde_core::de::Error::invalid_value( + serde_core::de::Unexpected::Str(version), + &"one of: \"0.1\"", + )); + } + } + } + } + "id" => { + if id.is_some() { + return Err(serde_core::de::Error::duplicate_field("id")); + } else { + id = Some(map.next_value()?); + } + } + "result" => { + if result.is_some() { + return Err(serde_core::de::Error::duplicate_field("result")); + } else { + result = Some(map.next_value()?); + } + } + "error" => { + if error.is_some() { + return Err(serde_core::de::Error::duplicate_field("error")); + } else { + error = Some(map.next_value()?); + } + } + field => { + return Err(serde_core::de::Error::unknown_field( + field, + &["duper_rpc", "id", "result", "error"], + )); + } + } + } + + match duper_rpc { + Some(DuperRpcVersion::DuperRpc01) => match (result, error) { + (Some(result), None) => { + let Some(id) = id else { + return Err(serde_core::de::Error::missing_field("id")); + }; + Ok(ResponseResult::Valid { + id, + result: result.static_clone(), + }) + } + (None, Some(error)) => Ok(ResponseResult::Invalid { id, error }), + (None, None) => Err(serde_core::de::Error::missing_field("result")), + (Some(_), Some(_)) => Err(serde_core::de::Error::custom( + "cannot have both result and error in response", + )), + }, + None => Err(serde_core::de::Error::missing_field("duper_rpc")), + } + } +} + +impl<'de> Deserialize<'de> for ResponseResult { + fn deserialize(deserializer: D) -> Result + where + D: serde_core::Deserializer<'de>, + { + deserializer.deserialize_map(ResponseResultVisitor {}) + } +} + +struct ResponseVisitor {} + +impl<'de> Visitor<'de> for ResponseVisitor { + type Value = Response; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a duper_rpc response") + } + + fn visit_map(self, map: A) -> Result + where + A: serde_core::de::MapAccess<'de>, + { + Ok(Response::Single(ResponseResultVisitor {}.visit_map(map)?)) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde_core::de::SeqAccess<'de>, + { + let mut vec = seq.size_hint().map(Vec::with_capacity).unwrap_or_default(); + while let Some(elem) = seq.next_element()? { + vec.push(elem); + } + Ok(Response::Batch(vec)) + } +} + +impl<'de> Deserialize<'de> for Response { + fn deserialize(deserializer: D) -> Result + where + D: serde_core::Deserializer<'de>, + { + Ok(deserializer.deserialize_any(ResponseVisitor {})?) + } +} diff --git a/duper_rpc/src/error.rs b/duper_rpc/src/error.rs index 1763114..fe91007 100644 --- a/duper_rpc/src/error.rs +++ b/duper_rpc/src/error.rs @@ -1,6 +1,6 @@ use duper::DuperValue; -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub enum Error { ParseError, InvalidRequest, diff --git a/duper_rpc/src/lib.rs b/duper_rpc/src/lib.rs index 6b80b6a..1fd0e7b 100644 --- a/duper_rpc/src/lib.rs +++ b/duper_rpc/src/lib.rs @@ -18,13 +18,13 @@ pub use crate::{ server::{Server, State}, }; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum RequestId { String(String), I64(i64), } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum DuperRpcVersion { DuperRpc01, } diff --git a/duper_rpc/src/request.rs b/duper_rpc/src/request.rs index ea3d282..8091d31 100644 --- a/duper_rpc/src/request.rs +++ b/duper_rpc/src/request.rs @@ -1,14 +1,18 @@ -use duper::DuperValue; +use duper::{ + DuperValue, + serde::{error::DuperSerdeError, ser::to_duper}, +}; +use serde_core::Serialize; use crate::{Error, RequestId}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Request { Single(RequestCall), Batch(Vec), } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum RequestCall { Valid { id: Option, @@ -20,3 +24,1385 @@ pub enum RequestCall { error: Error, }, } + +#[derive(Default)] +pub struct RequestBuilder; + +pub struct RequestBuilderSingle { + call: Result, +} + +pub struct RequestBuilderBatch { + calls: Result, DuperSerdeError>, +} + +impl Request { + pub fn builder() -> RequestBuilder { + RequestBuilder::new() + } +} + +impl RequestBuilder { + pub fn new() -> RequestBuilder { + RequestBuilder::default() + } + + pub fn request0(self, method: String, id: Option) -> RequestBuilderSingle { + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![], + }, + }), + } + } + + pub fn request1( + self, + method: String, + id: Option, + t1: &T1, + ) -> RequestBuilderSingle + where + T1: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone()], + }, + }), + } + } + + pub fn request2( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone(), t2.static_clone()], + }, + }), + } + } + + pub fn request3( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone(), t2.static_clone(), t3.static_clone()], + }, + }), + } + } + + pub fn request4( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + ], + }, + }), + } + } + + pub fn request5( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + ], + }, + }), + } + } + + pub fn request6( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + ], + }, + }), + } + } + + pub fn request7( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + t7: &T7, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + T7: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t7 = match to_duper(t7) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + t7.static_clone(), + ], + }, + }), + } + } + + pub fn request8( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + t7: &T7, + t8: &T8, + ) -> RequestBuilderSingle + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + T7: Serialize, + T8: Serialize, + { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t7 = match to_duper(t7) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + let t8 = match to_duper(t8) { + Ok(value) => value, + Err(error) => return RequestBuilderSingle { call: Err(error) }, + }; + RequestBuilderSingle { + call: Ok(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + t7.static_clone(), + t8.static_clone(), + ], + }, + }), + } + } +} + +impl RequestBuilderSingle { + pub fn build(self) -> Result { + self.call.map(Request::Single) + } + + pub fn request0(self, method: String, id: Option) -> RequestBuilderBatch { + match self.call { + Ok(call) => RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![], + }, + }, + ]), + }, + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request1(self, method: String, id: Option, t1: &T1) -> RequestBuilderBatch + where + T1: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone()], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request2( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone(), t2.static_clone()], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request3( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + ], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request4( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + ], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request5( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + ], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request6( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + ], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request7( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + t7: &T7, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + T7: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t7 = match to_duper(t7) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + t7.static_clone(), + ], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request8( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + t7: &T7, + t8: &T8, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + T7: Serialize, + T8: Serialize, + { + match self.call { + Ok(call) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t7 = match to_duper(t7) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t8 = match to_duper(t8) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + RequestBuilderBatch { + calls: Ok(vec![ + call, + RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + t7.static_clone(), + t8.static_clone(), + ], + }, + }, + ]), + } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } +} +impl RequestBuilderBatch { + pub fn build(self) -> Result { + self.calls.map(Request::Batch) + } + + pub fn request0(self, method: String, id: Option) -> RequestBuilderBatch { + match self.calls { + Ok(mut calls) => { + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request1(self, method: String, id: Option, t1: &T1) -> RequestBuilderBatch + where + T1: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone()], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request2( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone(), t2.static_clone()], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request3( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![t1.static_clone(), t2.static_clone(), t3.static_clone()], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request4( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + ], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request5( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + ], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request6( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + ], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request7( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + t7: &T7, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + T7: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t7 = match to_duper(t7) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + t7.static_clone(), + ], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } + + pub fn request8( + self, + method: String, + id: Option, + t1: &T1, + t2: &T2, + t3: &T3, + t4: &T4, + t5: &T5, + t6: &T6, + t7: &T7, + t8: &T8, + ) -> RequestBuilderBatch + where + T1: Serialize, + T2: Serialize, + T3: Serialize, + T4: Serialize, + T5: Serialize, + T6: Serialize, + T7: Serialize, + T8: Serialize, + { + match self.calls { + Ok(mut calls) => { + let t1 = match to_duper(t1) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t2 = match to_duper(t2) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t3 = match to_duper(t3) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t4 = match to_duper(t4) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t5 = match to_duper(t5) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t6 = match to_duper(t6) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t7 = match to_duper(t7) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + let t8 = match to_duper(t8) { + Ok(value) => value, + Err(error) => return RequestBuilderBatch { calls: Err(error) }, + }; + calls.push(RequestCall::Valid { + id, + method, + params: DuperValue::Tuple { + identifier: None, + inner: vec![ + t1.static_clone(), + t2.static_clone(), + t3.static_clone(), + t4.static_clone(), + t5.static_clone(), + t6.static_clone(), + t7.static_clone(), + t8.static_clone(), + ], + }, + }); + RequestBuilderBatch { calls: Ok(calls) } + } + Err(error) => RequestBuilderBatch { calls: Err(error) }, + } + } +} diff --git a/duper_rpc/src/response.rs b/duper_rpc/src/response.rs index de24264..e9f80be 100644 --- a/duper_rpc/src/response.rs +++ b/duper_rpc/src/response.rs @@ -2,13 +2,25 @@ use duper::DuperValue; use crate::{Error, RequestId}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Response { Single(ResponseResult), Batch(Vec), } -#[derive(Debug)] +impl IntoIterator for Response { + type Item = ResponseResult; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + match self { + Response::Single(result) => vec![result].into_iter(), + Response::Batch(result_vec) => result_vec.into_iter(), + } + } +} + +#[derive(Debug, Clone)] pub enum ResponseResult { Valid { id: RequestId, diff --git a/duper_rpc/src/ser.rs b/duper_rpc/src/ser.rs index c8c0e60..fa476ec 100644 --- a/duper_rpc/src/ser.rs +++ b/duper_rpc/src/ser.rs @@ -3,7 +3,7 @@ use serde_core::{ ser::{SerializeMap, SerializeSeq}, }; -use crate::{Error, RequestId, Response, ResponseResult}; +use crate::{Error, Request, RequestCall, RequestId, Response, ResponseResult}; impl Serialize for Error { fn serialize(&self, serializer: S) -> Result @@ -37,7 +37,7 @@ impl Serialize for Error { map.end() } Error::Custom(value) => { - let mut map = serializer.serialize_map(Some(1))?; + let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("type", "Custom")?; map.serialize_entry("value", value)?; map.end() @@ -77,19 +77,92 @@ impl Serialize for ResponseResult { } } +struct ResponseBatch<'a>(&'a Vec); + +impl<'a> Serialize for ResponseBatch<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde_core::Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.0.len()))?; + for result in self.0 { + seq.serialize_element(result)?; + } + seq.end() + } +} + impl Serialize for Response { fn serialize(&self, serializer: S) -> Result where S: serde_core::Serializer, { match self { - Response::Single(result) => result.serialize(serializer), + Response::Single(result) => serializer.serialize_newtype_struct("RpcResponse", result), Response::Batch(result_vec) => { - let mut seq = serializer.serialize_seq(Some(result_vec.len()))?; - for result in result_vec { - seq.serialize_element(result)?; + serializer.serialize_newtype_struct("RpcResponse", &ResponseBatch(result_vec)) + } + } + } +} + +impl Serialize for RequestCall { + fn serialize(&self, serializer: S) -> Result + where + S: serde_core::Serializer, + { + match self { + RequestCall::Valid { id, method, params } => match id { + Some(id) => { + let mut map = serializer.serialize_map(Some(4))?; + map.serialize_entry("duper_rpc", "0.1")?; + match id { + RequestId::String(id) => map.serialize_entry("id", id)?, + RequestId::I64(id) => map.serialize_entry("id", id)?, + } + map.serialize_entry("method", method)?; + map.serialize_entry("params", params)?; + map.end() } - seq.end() + None => { + let mut map = serializer.serialize_map(Some(3))?; + map.serialize_entry("duper_rpc", "0.1")?; + map.serialize_entry("method", method)?; + map.serialize_entry("params", params)?; + map.end() + } + }, + RequestCall::Invalid { .. } => Err(serde_core::ser::Error::custom( + "cannot serialize invalid RPC request", + )), + } + } +} + +struct RequestBatch<'a>(&'a Vec); + +impl<'a> Serialize for RequestBatch<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde_core::Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.0.len()))?; + for result in self.0 { + seq.serialize_element(result)?; + } + seq.end() + } +} + +impl Serialize for Request { + fn serialize(&self, serializer: S) -> Result + where + S: serde_core::Serializer, + { + match self { + Request::Single(call) => serializer.serialize_newtype_struct("RpcRequest", call), + Request::Batch(call_vec) => { + serializer.serialize_newtype_struct("RpcRequest", &RequestBatch(call_vec)) } } } diff --git a/duper_rpc/src/server.rs b/duper_rpc/src/server.rs index 8fab617..c14826d 100644 --- a/duper_rpc/src/server.rs +++ b/duper_rpc/src/server.rs @@ -281,7 +281,7 @@ where } #[cfg(test)] -mod rpc_tests { +mod rpc_server_tests { use std::borrow::Cow; use duper::{DuperFloat, DuperKey, DuperObject};