use crate::{ errors::{DispatchError, InternalError}, request::{unexpected_none_payload, EventRequest, FromRequest, Payload}, response::{EventResponse, Responder, ResponseBuilder, ToBytes}, util::ready::{ready, Ready}, }; use std::ops; pub struct Data(pub T); impl Data { pub fn into_inner(self) -> T { self.0 } } impl ops::Deref for Data { type Target = T; fn deref(&self) -> &T { &self.0 } } impl ops::DerefMut for Data { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } pub trait FromBytes: Sized { fn parse_from_bytes(bytes: &Vec) -> Result; } #[cfg(feature = "use_protobuf")] impl FromBytes for T where // https://stackoverflow.com/questions/62871045/tryfromu8-trait-bound-in-trait T: for<'a> std::convert::TryFrom<&'a Vec, Error = String>, { fn parse_from_bytes(bytes: &Vec) -> Result { T::try_from(bytes) } } #[cfg(feature = "use_serde")] impl FromBytes for T where T: serde::de::DeserializeOwned + 'static, { fn parse_from_bytes(bytes: &Vec) -> Result { let s = String::from_utf8_lossy(bytes); match serde_json::from_str::(s.as_ref()) { Ok(data) => Ok(data), Err(e) => Err(format!("{:?}", e)), } } } impl FromRequest for Data where T: FromBytes + 'static, { type Error = DispatchError; type Future = Ready>; #[inline] fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { match payload { Payload::None => ready(Err(unexpected_none_payload(req))), Payload::Bytes(bytes) => match T::parse_from_bytes(bytes) { Ok(data) => ready(Ok(Data(data))), Err(e) => ready(Err(InternalError::new(format!("{:?}", e)).into())), }, } } } impl Responder for Data where T: ToBytes, { fn respond_to(self, _request: &EventRequest) -> EventResponse { match self.into_inner().into_bytes() { Ok(bytes) => ResponseBuilder::Ok().data(bytes.to_vec()).build(), Err(e) => { let system_err: DispatchError = InternalError::new(format!("{:?}", e)).into(); system_err.into() }, } } } impl std::convert::From for Data where T: ToBytes, { fn from(val: T) -> Self { Data(val) } } impl std::convert::TryFrom<&Payload> for Data where T: FromBytes, { type Error = String; fn try_from(payload: &Payload) -> Result, Self::Error> { parse_payload(payload) } } impl std::convert::TryFrom for Data where T: FromBytes, { type Error = String; fn try_from(payload: Payload) -> Result, Self::Error> { parse_payload(&payload) } } fn parse_payload(payload: &Payload) -> Result, String> where T: FromBytes, { match payload { Payload::None => Err(format!("Parse fail, expected payload")), Payload::Bytes(bytes) => match T::parse_from_bytes(&bytes) { Ok(data) => Ok(Data(data)), Err(e) => Err(e), }, } } impl std::convert::TryInto for Data where T: ToBytes, { type Error = String; fn try_into(self) -> Result { let inner = self.into_inner(); let bytes = inner.into_bytes()?; Ok(Payload::Bytes(bytes)) } }