Skip to main content

tuwunel_core/utils/
json.rs

1//! Serialization helpers for raw and canonical JSON values.
2//!
3//! The conversion functions bridge Serde values to Ruma's raw and canonical
4//! representations. A generic deserializer adapts string-backed fields to types
5//! implementing `FromStr`.
6
7use std::{fmt, io, marker::PhantomData, str::FromStr};
8
9use ruma::{
10	CanonicalJsonError, CanonicalJsonObject, canonical_json::try_from_json_map, serde::Raw,
11};
12
13use crate::Result;
14
15/// An `io::Write` sink that counts bytes without buffering them.
16#[derive(Default)]
17struct Counter(usize);
18
19/// Serializes a value into Ruma's raw JSON representation.
20///
21/// The input is first converted to a `serde_json::Value`, then stored as
22/// `Raw<U>` without deserializing `U`. Serialization or JSON conversion
23/// failures are returned.
24pub fn to_raw<T: serde::Serialize, U>(input: T) -> Result<Raw<U>> {
25	Ok(serde_json::from_value(serde_json::to_value(input)?)?)
26}
27
28/// Converts a serializable value into a canonical JSON object.
29///
30/// The value must serialize to a JSON object. Serialization errors, non-object
31/// values, and data outside canonical JSON's representation are returned as
32/// `CanonicalJsonError`.
33pub fn to_canonical_object<T: serde::Serialize>(
34	value: T,
35) -> Result<CanonicalJsonObject, CanonicalJsonError> {
36	use CanonicalJsonError::SerDe;
37	use serde::ser::Error;
38
39	match serde_json::to_value(value).map_err(SerDe)? {
40		| serde_json::Value::Object(map) => try_from_json_map(map),
41		| _ => Err(SerDe(serde_json::Error::custom("Value must be an object"))),
42	}
43}
44
45/// Measures the length of a value's JSON serialization.
46///
47/// The value is written to a sink that counts bytes rather than retaining
48/// them, so the length costs no buffer. Serialization failures are returned.
49pub fn serialized_len<T: serde::Serialize>(value: &T) -> Result<usize> {
50	let mut counter = Counter::default();
51
52	serde_json::to_writer(&mut counter, value)?;
53
54	Ok(counter.0)
55}
56
57impl io::Write for Counter {
58	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
59		self.0 = self.0.saturating_add(buf.len());
60
61		Ok(buf.len())
62	}
63
64	fn flush(&mut self) -> io::Result<()> { Ok(()) }
65}
66
67/// Deserializes a string and parses it through `FromStr`.
68///
69/// Only string input is accepted. Parse failures become custom deserialization
70/// errors using their `Display` messages.
71pub fn deserialize_from_str<'de, D, T, E>(deserializer: D) -> Result<T, D::Error>
72where
73	D: serde::de::Deserializer<'de>,
74	T: FromStr<Err = E>,
75	E: fmt::Display,
76{
77	struct Visitor<T: FromStr<Err = E>, E>(PhantomData<T>);
78
79	impl<T, Err> serde::de::Visitor<'_> for Visitor<T, Err>
80	where
81		T: FromStr<Err = Err>,
82		Err: fmt::Display,
83	{
84		type Value = T;
85
86		fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
87			write!(formatter, "a parsable string")
88		}
89
90		fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
91		where
92			E: serde::de::Error,
93		{
94			v.parse().map_err(serde::de::Error::custom)
95		}
96	}
97
98	deserializer.deserialize_str(Visitor(PhantomData))
99}