ruma_common/
serde.rs

1//! (De)serialization helpers for other Ruma crates.
2//!
3//! Part of that is a fork of [serde_urlencoded], with support for sequences in `Deserialize` /
4//! `Serialize` structs (e.g. `Vec<Something>`) that are (de)serialized as `field=val1&field=val2`.
5//!
6//! [serde_urlencoded]: https://github.com/nox/serde_urlencoded
7
8use std::{fmt, marker::PhantomData};
9
10use serde::{
11    de::{self, SeqAccess, Visitor},
12    Deserialize, Deserializer,
13};
14use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
15
16pub mod base64;
17mod buf;
18pub mod can_be_empty;
19mod cow;
20pub mod duration;
21pub mod json_string;
22mod raw;
23pub mod single_element_seq;
24mod strings;
25pub mod test;
26
27pub use self::{
28    base64::{Base64, Base64DecodeError},
29    buf::{json_to_buf, slice_to_buf},
30    can_be_empty::{is_empty, CanBeEmpty},
31    cow::deserialize_cow_str,
32    raw::Raw,
33    strings::{
34        btreemap_deserialize_v1_powerlevel_values, deserialize_as_number_or_string,
35        deserialize_as_optional_number_or_string, deserialize_v1_powerlevel, empty_string_as_none,
36        none_as_empty_string,
37    },
38};
39
40/// The inner type of [`JsonValue::Object`].
41pub type JsonObject = serde_json::Map<String, JsonValue>;
42
43/// Check whether a value is equal to its default value.
44pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
45    *val == T::default()
46}
47
48/// Deserialize a `T` via `Option<T>`, falling back to `T::default()`.
49pub fn none_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
50where
51    D: Deserializer<'de>,
52    T: Default + Deserialize<'de>,
53{
54    Ok(Option::deserialize(deserializer)?.unwrap_or_default())
55}
56
57/// Simply returns `true`.
58///
59/// Useful for `#[serde(default = ...)]`.
60pub fn default_true() -> bool {
61    true
62}
63
64/// Simply dereferences the given bool.
65///
66/// Useful for `#[serde(skip_serializing_if = ...)]`.
67#[allow(clippy::trivially_copy_pass_by_ref)]
68pub fn is_true(b: &bool) -> bool {
69    *b
70}
71
72/// Helper function for `serde_json::value::RawValue` deserialization.
73pub fn from_raw_json_value<'a, T, E>(val: &'a RawJsonValue) -> Result<T, E>
74where
75    T: Deserialize<'a>,
76    E: de::Error,
77{
78    serde_json::from_str(val.get()).map_err(E::custom)
79}
80
81/// Helper function for ignoring invalid items in a `Vec`, instead letting them cause the entire
82/// `Vec` to fail deserialization
83pub fn ignore_invalid_vec_items<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
84where
85    D: Deserializer<'de>,
86    T: Deserialize<'de>,
87{
88    struct SkipInvalid<T>(PhantomData<T>);
89
90    impl<'de, T> Visitor<'de> for SkipInvalid<T>
91    where
92        T: Deserialize<'de>,
93    {
94        type Value = Vec<T>;
95
96        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
97            formatter.write_str("Vec with possibly invalid items")
98        }
99
100        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
101        where
102            A: SeqAccess<'de>,
103        {
104            let mut vec = Vec::new();
105
106            while let Some(result) = seq.next_element::<T>().transpose() {
107                let Ok(elem) = result else {
108                    continue;
109                };
110
111                vec.push(elem);
112            }
113
114            Ok(vec)
115        }
116    }
117
118    deserializer.deserialize_seq(SkipInvalid(PhantomData))
119}
120
121pub use ruma_macros::{
122    AsRefStr, AsStrAsRefStr, DebugAsRefStr, DeserializeFromCowStr, DisplayAsRefStr, FromString,
123    OrdAsRefStr, PartialEqAsRefStr, PartialOrdAsRefStr, SerializeAsRefStr, StringEnum,
124    _FakeDeriveSerde,
125};