alef 0.115.4

Opinionated polyglot binding generator for Rust libraries
Documentation

impl<'de> serde::Deserialize<'de> for {{ enum_name }} {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        use serde::de::Error;
        let mut object = match <serde_json::Value as serde::Deserialize>::deserialize(deserializer)? {
            serde_json::Value::Object(object) => object,
            serde_json::Value::Null => serde_json::Map::new(),
            _ => return Err(D::Error::custom("expected an object for {{ enum_name }}")),
        };
        let tag = match object.remove("{{ tag_field }}") {
            Some(serde_json::Value::String(tag)) => tag,
            Some(_) => return Err(D::Error::custom("the {{ tag_field }} of {{ enum_name }} must be a string")),
            None => String::new(),
        };
        let mut value = Self {
            {{ tag_field }}_tag: tag.clone(),
            ..Default::default()
        };
        match tag.as_str() {
{{ arms }}            _ => {}
        }
        Ok(value)
    }
}

impl {{ enum_name }} {
    /// The payload of a variant: the object nested under `key` when it is the only entry, else the
    /// whole object (serde writes the payload fields next to the tag).
    fn payload<T: serde::de::DeserializeOwned>(
        mut object: serde_json::Map<String, serde_json::Value>,
        key: &str,
    ) -> Result<T, serde_json::Error> {
        let nested = object.len() == 1 && object.get(key).is_some_and(serde_json::Value::is_object);
        let source = if nested {
            object.remove(key).unwrap_or_default()
        } else {
            serde_json::Value::Object(object)
        };
        serde_json::from_value(source)
    }
}