pub mod bool { /// Function that always returns `true`, for use in `serde(default)` attributes. pub fn yes() -> bool { true } } pub mod string { use std::fmt::Display; use std::str::FromStr; use serde::{de, Deserialize, Deserializer, Serializer}; pub fn serialize(value: &T, serializer: S) -> Result where T: Display, S: Serializer, { serializer.collect_str(value) } pub fn deserialize<'de, T, D>(deserializer: D) -> Result where T: FromStr, T::Err: Display, D: Deserializer<'de>, { String::deserialize(deserializer)? .parse() .map_err(de::Error::custom) } } /// Unlike the default `serde` instances from `localtime`, this encodes and decodes using seconds /// instead of milliseconds. pub mod localtime { pub mod time { use localtime::LocalTime; use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(value: &LocalTime, serializer: S) -> Result where S: Serializer, { serializer.serialize_u64(value.as_secs()) } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let seconds = u64::deserialize(deserializer)?; Ok(LocalTime::from_secs(seconds)) } } pub mod option { pub mod time { use localtime::LocalTime; use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(value: &Option, serializer: S) -> Result where S: Serializer, { match value { Some(time) => serializer.serialize_some(&time.as_secs()), None => serializer.serialize_none(), } } pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let option = Option::::deserialize(deserializer)?; match option { Some(seconds) => Ok(Some(LocalTime::from_secs(seconds))), None => Ok(None), } } } } pub mod duration { use localtime::LocalDuration; use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(value: &LocalDuration, serializer: S) -> Result where S: Serializer, { serializer.serialize_u64(value.as_secs()) } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let seconds = u64::deserialize(deserializer)?; Ok(LocalDuration::from_secs(seconds)) } } } /// Return true if the given value is the default for that type. pub fn is_default(t: &T) -> bool { t == &T::default() } /// Deserialize a value, but if it fails, return the default value. pub fn ok_or_default<'de, T, D>(deserializer: D) -> Result where T: serde::Deserialize<'de> + Default, D: serde::Deserializer<'de>, { let v: serde_json::Value = serde::Deserialize::deserialize(deserializer)?; Ok(T::deserialize(v).unwrap_or_default()) } #[cfg(test)] #[allow(clippy::unwrap_used)] mod test { use super::*; use ::localtime::LocalTime; #[test] fn test_localtime() { #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)] struct Test { time: LocalTime, } let value = Test { time: LocalTime::from_millis(1699636852107), }; assert_eq!( serde_json::from_str::(r#"{"time":1699636852107}"#).unwrap(), value ); assert_eq!( serde_json::from_str::(serde_json::to_string(&value).unwrap().as_str()).unwrap(), value ); } #[test] // Tests serialization into seconds instead of milliseconds. fn test_localtime_ext() { #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)] struct Test { #[serde(with = "localtime::time")] time: LocalTime, } let value = Test { time: LocalTime::from_secs(1699636852107), }; assert_eq!( serde_json::from_str::(r#"{"time":1699636852107}"#).unwrap(), value ); assert_eq!( serde_json::from_str::(serde_json::to_string(&value).unwrap().as_str()).unwrap(), value ); } }