1use std::{fmt, marker::PhantomData};
9
10use serde::{
11 de::{self, DeserializeOwned, SeqAccess, Visitor},
12 Deserialize, Deserializer,
13};
14use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
15use tracing::debug;
16
17pub mod base64;
18mod buf;
19pub mod can_be_empty;
20mod cow;
21pub mod duration;
22pub mod json_string;
23mod raw;
24pub mod single_element_seq;
25mod strings;
26pub mod test;
27
28pub use self::{
29 base64::{Base64, Base64DecodeError},
30 buf::{json_to_buf, slice_to_buf},
31 can_be_empty::{is_empty, CanBeEmpty},
32 cow::deserialize_cow_str,
33 raw::Raw,
34 strings::{
35 btreemap_deserialize_v1_powerlevel_values, deserialize_as_number_or_string,
36 deserialize_as_optional_number_or_string, deserialize_v1_powerlevel, empty_string_as_none,
37 none_as_empty_string,
38 },
39};
40
41pub type JsonObject = serde_json::Map<String, JsonValue>;
43
44pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
46 *val == T::default()
47}
48
49pub fn none_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
51where
52 D: Deserializer<'de>,
53 T: Default + Deserialize<'de>,
54{
55 Ok(Option::deserialize(deserializer)?.unwrap_or_default())
56}
57
58pub fn default_true() -> bool {
62 true
63}
64
65#[allow(clippy::trivially_copy_pass_by_ref)]
69pub fn is_true(b: &bool) -> bool {
70 *b
71}
72
73pub fn from_raw_json_value<'a, T, E>(val: &'a RawJsonValue) -> Result<T, E>
75where
76 T: Deserialize<'a>,
77 E: de::Error,
78{
79 serde_json::from_str(val.get()).map_err(E::custom)
80}
81
82pub fn default_on_error<'de, D, T>(deserializer: D) -> Result<T, D::Error>
88where
89 D: Deserializer<'de>,
90 T: DeserializeOwned + Default,
91{
92 let value = match Box::<RawJsonValue>::deserialize(deserializer) {
93 Ok(value) => value,
94 Err(error) => {
95 debug!("deserialization error, using default value: {error}");
96 return Ok(T::default());
97 }
98 };
99
100 Ok(from_raw_json_value(&value).unwrap_or_else(|error: D::Error| {
101 debug!("deserialization error, using default value: {error}");
102 T::default()
103 }))
104}
105
106pub fn ignore_invalid_vec_items<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
109where
110 D: Deserializer<'de>,
111 T: Deserialize<'de>,
112{
113 struct SkipInvalid<T>(PhantomData<T>);
114
115 impl<'de, T> Visitor<'de> for SkipInvalid<T>
116 where
117 T: Deserialize<'de>,
118 {
119 type Value = Vec<T>;
120
121 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
122 formatter.write_str("Vec with possibly invalid items")
123 }
124
125 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
126 where
127 A: SeqAccess<'de>,
128 {
129 let mut vec = Vec::new();
130
131 while let Some(result) = seq.next_element::<T>().transpose() {
132 let Ok(elem) = result else {
133 continue;
134 };
135
136 vec.push(elem);
137 }
138
139 Ok(vec)
140 }
141 }
142
143 deserializer.deserialize_seq(SkipInvalid(PhantomData))
144}
145
146pub use ruma_macros::{
147 AsRefStr, AsStrAsRefStr, DebugAsRefStr, DeserializeFromCowStr, DisplayAsRefStr, FromString,
148 OrdAsRefStr, PartialEqAsRefStr, PartialOrdAsRefStr, SerializeAsRefStr, StringEnum,
149 _FakeDeriveSerde,
150};