use std::fmt;
use serde::Deserialize;
#[derive(Debug)]
pub(crate) struct Discard;
impl fmt::Display for Discard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("unknown variant")
}
}
impl std::error::Error for Discard {}
impl serde::de::Error for Discard {
fn custom<T: fmt::Display>(_msg: T) -> Self {
Discard
}
}
pub(crate) fn parse_known<T: serde::de::DeserializeOwned>(s: &str) -> Option<T> {
use serde::de::IntoDeserializer;
let de: serde::de::value::StrDeserializer<'_, Discard> = s.into_deserializer();
T::deserialize(de).ok()
}
pub(crate) fn deserialize_extensible<'de, D, K, O>(
deserializer: D,
known: fn(K) -> O,
unknown: fn(String) -> O,
) -> Result<O, D::Error>
where
D: serde::Deserializer<'de>,
K: serde::de::DeserializeOwned,
{
let s = String::deserialize(deserializer)?;
Ok(match parse_known::<K>(&s) {
Some(k) => known(k),
None => unknown(s),
})
}