use std::{fmt, marker::PhantomData};
use serde::{
Deserialize, Deserializer,
de::{self, DeserializeOwned, SeqAccess, Visitor},
};
use serde_json::{Value as JsonValue, value::RawValue as RawJsonValue};
use tracing::debug;
pub mod base64;
mod buf;
pub mod can_be_empty;
mod cow;
pub mod duration;
pub mod json_string;
mod raw;
pub mod single_element_seq;
mod strings;
pub mod test;
pub use self::{
base64::{Base64, Base64DecodeError},
buf::{json_to_buf, slice_to_buf},
can_be_empty::{CanBeEmpty, is_empty},
cow::deserialize_cow_str,
raw::{JsonCastable, Raw},
strings::{
btreemap_deserialize_v1_powerlevel_values, deserialize_as_number_or_string,
deserialize_as_optional_number_or_string, deserialize_v1_powerlevel, empty_string_as_none,
none_as_empty_string,
},
};
pub type JsonObject = serde_json::Map<String, JsonValue>;
pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
*val == T::default()
}
pub fn none_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: Default + Deserialize<'de>,
{
Ok(Option::deserialize(deserializer)?.unwrap_or_default())
}
pub fn default_true() -> bool {
true
}
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn is_true(b: &bool) -> bool {
*b
}
pub fn from_raw_json_value<'a, T, E>(val: &'a RawJsonValue) -> Result<T, E>
where
T: Deserialize<'a>,
E: de::Error,
{
serde_json::from_str(val.get()).map_err(E::custom)
}
pub fn default_on_error<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: DeserializeOwned + Default,
{
let value = match Box::<RawJsonValue>::deserialize(deserializer) {
Ok(value) => value,
Err(error) => {
debug!("deserialization error, using default value: {error}");
return Ok(T::default());
}
};
Ok(from_raw_json_value(&value).unwrap_or_else(|error: D::Error| {
debug!("deserialization error, using default value: {error}");
T::default()
}))
}
pub fn ignore_invalid_vec_items<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
{
struct SkipInvalid<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for SkipInvalid<T>
where
T: Deserialize<'de>,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("Vec with possibly invalid items")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut vec = Vec::new();
while let Some(result) = seq.next_element::<T>().transpose() {
let Ok(elem) = result else {
continue;
};
vec.push(elem);
}
Ok(vec)
}
}
deserializer.deserialize_seq(SkipInvalid(PhantomData))
}
pub use ruma_macros::{
_FakeDeriveSerde, AsRefStr, AsStrAsRefStr, DebugAsRefStr, DeserializeFromCowStr,
DisplayAsRefStr, EqAsRefStr, FromString, OrdAsRefStr, SerializeAsRefStr, StringEnum,
};