use std::marker::PhantomData;
use std::str::FromStr;
use serde::Deserialize;
use serde_with::DeserializeAs;
pub struct MapOrString;
impl<'de, T> DeserializeAs<'de, T> for MapOrString
where
T: Deserialize<'de> + FromStr,
T::Err: std::fmt::Display,
{
fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
use serde::de::Visitor;
struct MapOrStringVisitor<T>(PhantomData<T>);
impl<'de, T> Visitor<'de> for MapOrStringVisitor<T>
where
T: Deserialize<'de> + FromStr,
T::Err: std::fmt::Display,
{
type Value = T;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "map or string")
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
use serde::de::value::MapAccessDeserializer;
T::deserialize(MapAccessDeserializer::new(map))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
v.parse().map_err(Error::custom)
}
}
deserializer.deserialize_any(MapOrStringVisitor(PhantomData))
}
}
#[allow(dead_code)]
pub struct Flatten<D>(PhantomData<D>);
impl<'de, T, D> DeserializeAs<'de, Vec<T>> for Flatten<D>
where
T: Deserialize<'de>,
D: DeserializeAs<'de, Vec<T>>,
{
fn deserialize_as<De>(deserializer: De) -> Result<Vec<T>, De::Error>
where
De: serde::Deserializer<'de>,
{
Ok(<Vec<D>>::deserialize_as(deserializer)?
.into_iter()
.flatten()
.collect())
}
}
pub struct SingletonMap;
impl<'de, T> DeserializeAs<'de, T> for SingletonMap
where
T: Deserialize<'de>,
{
#[inline]
fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
where
D: serde::Deserializer<'de>,
{
serde_yaml_ng::with::singleton_map::deserialize(deserializer)
}
}