gproxy-protocol 3.0.0-alpha.0

GPROXY v3 protocol model: operation taxonomy, wire kinds, and the OperationSpec registry
Documentation
use std::fmt;

use serde::Deserialize;

#[derive(Debug)]
pub(crate) struct Discard;

impl fmt::Display for Discard {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("unknown variant")
    }
}

impl std::error::Error for Discard {}

impl serde::de::Error for Discard {
    fn custom<T: fmt::Display>(_: T) -> Self {
        Self
    }
}

pub(crate) fn parse_known<T: serde::de::DeserializeOwned>(value: &str) -> Option<T> {
    use serde::de::IntoDeserializer;

    let deserializer: serde::de::value::StrDeserializer<'_, Discard> = value.into_deserializer();
    T::deserialize(deserializer).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 value = String::deserialize(deserializer)?;
    Ok(match parse_known::<K>(&value) {
        Some(value) => known(value),
        None => unknown(value),
    })
}