ruma_serde/raw.rs
1use std::{
2 clone::Clone,
3 fmt::{self, Debug, Formatter},
4 marker::PhantomData,
5 mem,
6};
7
8use serde::{
9 de::{Deserialize, Deserializer, IgnoredAny, MapAccess, Visitor},
10 ser::{Serialize, Serializer},
11};
12use serde_json::value::{to_raw_value as to_raw_json_value, RawValue as RawJsonValue};
13
14use crate::cow::MyCowStr;
15
16/// A wrapper around `Box<RawValue>`, to be used in place of any type in the Matrix endpoint
17/// definition to allow request and response types to contain that said type represented by
18/// the generic argument `Ev`.
19///
20/// Ruma offers the `Raw` wrapper to enable passing around JSON text that is only partially
21/// validated. This is useful when a client receives events that do not follow the spec perfectly
22/// or a server needs to generate reference hashes with the original canonical JSON string.
23/// All event structs and enums implement `Serialize` / `Deserialize`, `Raw` should be used
24/// to pass around events in a lossless way.
25///
26/// ```no_run
27/// # use serde::Deserialize;
28/// # use ruma_serde::Raw;
29/// # #[derive(Deserialize)]
30/// # struct AnyRoomEvent;
31///
32/// let json = r#"{ "type": "imagine a full event", "content": {...} }"#;
33///
34/// let deser = serde_json::from_str::<Raw<AnyRoomEvent>>(json)
35/// .unwrap() // the first Result from serde_json::from_str, will not fail
36/// .deserialize() // deserialize to the inner type
37/// .unwrap(); // finally get to the AnyRoomEvent
38/// ```
39#[repr(transparent)]
40pub struct Raw<T> {
41 json: Box<RawJsonValue>,
42 _ev: PhantomData<T>,
43}
44
45impl<T> Raw<T> {
46 /// Create a `Raw` by serializing the given `T`.
47 ///
48 /// Shorthand for `serde_json::value::to_raw_value(val).map(Raw::from_json)`, but specialized to
49 /// `T`.
50 ///
51 /// # Errors
52 ///
53 /// Fails if `T`s [`Serialize`] implementation fails.
54 pub fn new(val: &T) -> serde_json::Result<Self>
55 where
56 T: Serialize,
57 {
58 to_raw_json_value(val).map(Self::from_json)
59 }
60
61 /// Create a `Raw` from a boxed `RawValue`.
62 pub fn from_json(json: Box<RawJsonValue>) -> Self {
63 Self { json, _ev: PhantomData }
64 }
65
66 /// Access the underlying json value.
67 pub fn json(&self) -> &RawJsonValue {
68 &self.json
69 }
70
71 /// Convert `self` into the underlying json value.
72 pub fn into_json(self) -> Box<RawJsonValue> {
73 self.json
74 }
75
76 /// Try to access a given field inside this `Raw`, assuming it contains an object.
77 ///
78 /// Returns `Err(_)` when the contained value is not an object, or the field exists but is fails
79 /// to deserialize to the expected type.
80 ///
81 /// Returns `Ok(None)` when the field doesn't exist or is `null`.
82 ///
83 /// # Example
84 ///
85 /// ```no_run
86 /// # type CustomMatrixEvent = ();
87 /// # fn foo() -> serde_json::Result<()> {
88 /// # let raw_event: ruma_serde::Raw<()> = todo!();
89 /// if raw_event.get_field::<String>("type")?.as_deref() == Some("org.custom.matrix.event") {
90 /// let event = raw_event.deserialize_as::<CustomMatrixEvent>()?;
91 /// // ...
92 /// }
93 /// # Ok(())
94 /// # }
95 /// ```
96 pub fn get_field<'a, U>(&'a self, field_name: &str) -> serde_json::Result<Option<U>>
97 where
98 U: Deserialize<'a>,
99 {
100 struct SingleFieldVisitor<'b, T> {
101 field_name: &'b str,
102 _phantom: PhantomData<T>,
103 }
104
105 impl<'b, T> SingleFieldVisitor<'b, T> {
106 fn new(field_name: &'b str) -> Self {
107 Self { field_name, _phantom: PhantomData }
108 }
109 }
110
111 impl<'b, 'de, T> Visitor<'de> for SingleFieldVisitor<'b, T>
112 where
113 T: Deserialize<'de>,
114 {
115 type Value = Option<T>;
116
117 fn expecting(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
118 formatter.write_str("a string")
119 }
120
121 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
122 where
123 A: MapAccess<'de>,
124 {
125 let mut res = None;
126 while let Some(key) = map.next_key::<MyCowStr<'_>>()? {
127 if key.get() == self.field_name {
128 res = Some(map.next_value()?);
129 } else {
130 map.next_value::<IgnoredAny>()?;
131 }
132 }
133
134 Ok(res)
135 }
136 }
137
138 let mut deserializer = serde_json::Deserializer::from_str(self.json().get());
139 deserializer.deserialize_map(SingleFieldVisitor::new(field_name))
140 }
141
142 /// Try to deserialize the JSON as the expected type.
143 pub fn deserialize<'a>(&'a self) -> serde_json::Result<T>
144 where
145 T: Deserialize<'a>,
146 {
147 serde_json::from_str(self.json.get())
148 }
149
150 /// Try to deserialize the JSON as a custom type.
151 pub fn deserialize_as<'a, U>(&'a self) -> serde_json::Result<U>
152 where
153 U: Deserialize<'a>,
154 {
155 serde_json::from_str(self.json.get())
156 }
157
158 /// Turns `Raw<T>` into `Raw<U>` without changing the underlying JSON.
159 ///
160 /// This is useful for turning raw specific event types into raw event enum types.
161 pub fn cast<U>(self) -> Raw<U> {
162 Raw::from_json(self.into_json())
163 }
164
165 /// Turns `&Raw<T>` into `&Raw<U>` without changing the underlying JSON.
166 ///
167 /// This is useful for turning raw specific event types into raw event enum types.
168 pub fn cast_ref<U>(&self) -> &Raw<U> {
169 unsafe { mem::transmute(self) }
170 }
171}
172
173impl<T> Clone for Raw<T> {
174 fn clone(&self) -> Self {
175 Self::from_json(self.json.clone())
176 }
177}
178
179impl<T> Debug for Raw<T> {
180 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
181 use std::any::type_name;
182 f.debug_struct(&format!("Raw::<{}>", type_name::<T>())).field("json", &self.json).finish()
183 }
184}
185
186impl<'de, T> Deserialize<'de> for Raw<T> {
187 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
188 where
189 D: Deserializer<'de>,
190 {
191 Box::<RawJsonValue>::deserialize(deserializer).map(Self::from_json)
192 }
193}
194
195impl<T> Serialize for Raw<T> {
196 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
197 where
198 S: Serializer,
199 {
200 self.json.serialize(serializer)
201 }
202}