use iso8601::Duration;
use serde::{Deserialize, Deserializer};
use serde_with::DeserializeAs;
pub struct Iso8601DurationDeserialize;
impl<'de> DeserializeAs<'de, Duration> for Iso8601DurationDeserialize {
fn deserialize_as<D: Deserializer<'de>>(deserializer: D) -> Result<Duration, D::Error> {
let s = String::deserialize(deserializer)?;
iso8601::duration(&s).map_err(|msg| serde::de::Error::custom(msg))
}
}
pub use flattened_xml_attr_impl::flattened_xml_attr;
mod flattened_xml_attr_impl {
use fmt::Display;
use serde::{Deserialize, Deserializer};
use std::fmt;
pub fn flattened_xml_attr<'de, D: Deserializer<'de>, T: FromXmlStr + Deserialize<'de>>(
deserializer: D,
) -> Result<T, D::Error> {
#[derive(Deserialize)]
#[serde(untagged)]
enum TypeOrString<T> {
Ty(T),
String(String),
}
match TypeOrString::<T>::deserialize(deserializer)? {
TypeOrString::Ty(t) => Ok(t),
TypeOrString::String(s) => T::from_str(&s).map_err(serde::de::Error::custom),
}
}
pub trait FromXmlStr: Sized {
type Error: Display;
fn from_str(s: &str) -> Result<Self, Self::Error>;
fn deserialize_from_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error>;
}
macro_rules! impl_from_xml_str_as_from_str {
($($t:ty)*) => {
$(
impl FromXmlStr for $t {
type Error = <$t as std::str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Error> {
s.parse()
}
fn deserialize_from_type<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
<$t>::deserialize(deserializer)
}
}
)*
};
}
impl_from_xml_str_as_from_str! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
f32 f64 char
}
impl FromXmlStr for bool {
type Error = String;
fn from_str(s: &str) -> Result<Self, Self::Error> {
match s {
"true" | "1" => Ok(true),
"false" | "0" => Ok(false),
s => Err(format!("\"{}\" is not a valid bool", s)),
}
}
fn deserialize_from_type<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
bool::deserialize(deserializer)
}
}
}