Skip to main content

tuwunel_core/utils/
json.rs

1use std::{fmt, marker::PhantomData, str::FromStr};
2
3use ruma::{
4	CanonicalJsonError, CanonicalJsonObject, canonical_json::try_from_json_map, serde::Raw,
5};
6
7use crate::Result;
8
9/// Perform a round-trip through serde_json starting with a native type T and
10/// ending with a Ruma `Raw<U>` which is usually just T.
11pub fn to_raw<T: serde::Serialize, U>(input: T) -> Result<Raw<U>> {
12	Ok(serde_json::from_value(serde_json::to_value(input)?)?)
13}
14
15/// Fallible conversion from any value that implements `Serialize` to a
16/// `CanonicalJsonObject`.
17///
18/// `value` must serialize to an `serde_json::Value::Object`.
19pub fn to_canonical_object<T: serde::Serialize>(
20	value: T,
21) -> Result<CanonicalJsonObject, CanonicalJsonError> {
22	use CanonicalJsonError::SerDe;
23	use serde::ser::Error;
24
25	match serde_json::to_value(value).map_err(SerDe)? {
26		| serde_json::Value::Object(map) => try_from_json_map(map),
27		| _ => Err(SerDe(serde_json::Error::custom("Value must be an object"))),
28	}
29}
30
31pub fn deserialize_from_str<'de, D, T, E>(deserializer: D) -> Result<T, D::Error>
32where
33	D: serde::de::Deserializer<'de>,
34	T: FromStr<Err = E>,
35	E: fmt::Display,
36{
37	struct Visitor<T: FromStr<Err = E>, E>(PhantomData<T>);
38
39	impl<T, Err> serde::de::Visitor<'_> for Visitor<T, Err>
40	where
41		T: FromStr<Err = Err>,
42		Err: fmt::Display,
43	{
44		type Value = T;
45
46		fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
47			write!(formatter, "a parsable string")
48		}
49
50		fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
51		where
52			E: serde::de::Error,
53		{
54			v.parse().map_err(serde::de::Error::custom)
55		}
56	}
57
58	deserializer.deserialize_str(Visitor(PhantomData))
59}