use std::{ clone::Clone, fmt::{self, Debug, Formatter}, marker::PhantomData, }; use serde::{ de::{Deserialize, Deserializer}, ser::{Serialize, Serializer}, }; use serde_json::value::RawValue; use crate::{ error::{InvalidEvent, InvalidEventKind}, TryFromRaw, }; /// A wrapper around `Box`, to be used in place of event [content] [collection] types in /// Matrix endpoint definition to allow request and response types to contain unknown events in /// addition to the known event(s) represented by the generic argument `Ev`. pub struct EventJson { json: Box, _ev: PhantomData, } impl EventJson { fn new(json: Box) -> Self { Self { json, _ev: PhantomData, } } /// Access the underlying `RawValue`. pub fn json(&self) -> &RawValue { &self.json } } impl EventJson { /// Try to deserialize the JSON into the expected event type. pub fn deserialize(&self) -> Result { let raw_ev: T::Raw = match serde_json::from_str(self.json.get()) { Ok(raw) => raw, Err(error) => { return Err(InvalidEvent { message: error.to_string(), kind: InvalidEventKind::Deserialization, }); } }; match T::try_from_raw(raw_ev) { Ok(value) => Ok(value), Err(err) => Err(InvalidEvent { message: err.to_string(), kind: InvalidEventKind::Validation, }), } } } impl From<&T> for EventJson { fn from(val: &T) -> Self { Self::new(serde_json::value::to_raw_value(val).unwrap()) } } // Without the `TryFromRaw` bound, this would conflict with the next impl below // We could remove the `TryFromRaw` bound once specialization is stabilized. impl From for EventJson { fn from(val: T) -> Self { Self::from(&val) } } impl From> for EventJson { fn from(json: Box) -> Self { Self::new(json) } } impl Clone for EventJson { fn clone(&self) -> Self { Self::new(self.json.clone()) } } impl Debug for EventJson { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { use std::any::type_name; f.debug_struct(&format!("EventJson::<{}>", type_name::())) .field("json", &self.json) .finish() } } impl PartialEq for EventJson { fn eq(&self, other: &Self) -> bool { self.json.get() == other.json.get() } } impl<'de, T> Deserialize<'de> for EventJson { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Box::::deserialize(deserializer).map(Self::new) } } impl Serialize for EventJson { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.json.serialize(serializer) } }