use std::{ clone::Clone, fmt::{self, Debug, Formatter}, marker::PhantomData, }; use serde::{ de::{Deserialize, DeserializeOwned, Deserializer, IgnoredAny, MapAccess, Visitor}, ser::{Serialize, Serializer}, }; use serde_json::value::RawValue; use crate::cow::MyCowStr; /// A wrapper around `Box`, to be used in place of any type in the Matrix endpoint /// definition to allow request and response types to contain that said type represented by /// the generic argument `Ev`. /// /// Ruma offers the `Raw` wrapper to enable passing around JSON text that is only partially /// validated. This is useful when a client receives events that do not follow the spec perfectly /// or a server needs to generate reference hashes with the original canonical JSON string. /// All event structs and enums implement `Serialize` / `Deserialize`, `Raw` should be used /// to pass around events in a lossless way. /// /// ```no_run /// # use serde::Deserialize; /// # use ruma_serde::Raw; /// # #[derive(Deserialize)] /// # struct AnyRoomEvent; /// /// let json = r#"{ "type": "imagine a full event", "content": {...} }"#; /// /// let deser = serde_json::from_str::>(json) /// .unwrap() // the first Result from serde_json::from_str, will not fail /// .deserialize() // deserialize to the inner type /// .unwrap(); // finally get to the AnyRoomEvent /// ``` pub struct Raw { json: Box, _ev: PhantomData, } impl Raw { fn new(json: Box) -> Self { Self { json, _ev: PhantomData } } /// Create a `Raw` from a boxed `RawValue`. pub fn from_json(raw: Box) -> Self { Self::new(raw) } /// Access the underlying json value. pub fn json(&self) -> &RawValue { &self.json } /// Convert `self` into the underlying json value. pub fn into_json(self) -> Box { self.json } /// Try to access a given field inside this `Raw`, assuming it contains an /// object. /// /// Returns `Err(_)` when the contained value is not an object, or the field /// exists but is fails to deserialize to the expected type. /// /// Returns `Ok(None)` when the field doesn't exist or is `null`. /// /// # Example /// /// ```no_run /// # type CustomMatrixEvent = (); /// # fn foo() -> serde_json::Result<()> { /// # let raw_event: ruma_serde::Raw<()> = todo!(); /// if raw_event.get_field::("type")?.as_deref() == Some("org.custom.matrix.event") { /// let event = raw_event.deserialize_as::()?; /// // ... /// } /// # Ok(()) /// # } /// ``` pub fn get_field<'a, U>(&'a self, field_name: &str) -> serde_json::Result> where U: Deserialize<'a>, { struct SingleFieldVisitor<'b, T> { field_name: &'b str, _phantom: PhantomData, } impl<'b, T> SingleFieldVisitor<'b, T> { fn new(field_name: &'b str) -> Self { Self { field_name, _phantom: PhantomData } } } impl<'b, 'de, T> Visitor<'de> for SingleFieldVisitor<'b, T> where T: Deserialize<'de>, { type Value = Option; fn expecting(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result { formatter.write_str("a string") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut res = None; while let Some(key) = map.next_key::>()? { if key.get() == self.field_name { res = Some(map.next_value()?); } else { map.next_value::()?; } } Ok(res) } } let mut deserializer = serde_json::Deserializer::from_str(self.json().get()); deserializer.deserialize_map(SingleFieldVisitor::new(field_name)) } /// Try to deserialize the JSON as a custom type. pub fn deserialize_as(&self) -> serde_json::Result where U: DeserializeOwned, { serde_json::from_str(self.json.get()) } } impl Raw where T: DeserializeOwned, { /// Try to deserialize the JSON as the expected type. pub fn deserialize(&self) -> serde_json::Result { serde_json::from_str(self.json.get()) } } impl From<&T> for Raw { fn from(val: &T) -> Self { Self::new(serde_json::value::to_raw_value(val).unwrap()) } } // With specialization a fast path from impl for `impl From From for Raw { fn from(val: T) -> Self { Self::from(&val) } } impl Clone for Raw { fn clone(&self) -> Self { Self::new(self.json.clone()) } } impl Debug for Raw { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { use std::any::type_name; f.debug_struct(&format!("Raw::<{}>", type_name::())).field("json", &self.json).finish() } } impl<'de, T> Deserialize<'de> for Raw { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Box::::deserialize(deserializer).map(Self::new) } } impl Serialize for Raw { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.json.serialize(serializer) } }