alef 0.25.37

Opinionated polyglot binding generator for Rust libraries
Documentation
#[derive(Clone)]
#[pyclass(frozen)]
pub struct {{ name }} {
    pub(crate) inner: {{ core_path }},
}

#[pymethods]
impl {{ name }} {
{%- if has_sanitized %}
{{ string_methods_content }}
{{ variant_accessors_content }}
{{ serde_tag_content }}
{%- else %}
    #[new]
    #[pyo3(signature = (value=None, **kwargs))]
    fn new(
        py: Python<'_>,
        value: Option<&Bound<'_, pyo3::types::PyAny>>,
        kwargs: Option<&Bound<'_, pyo3::types::PyDict>>,
    ) -> PyResult<Self> {
        // Accept three call shapes:
        //   {{ name }}("variant_name")                     -> unit variant
        //   {{ name }}({"type": "variant", ...})           -> dict positional
        //   {{ name }}(type="variant", field=...)          -> kwargs (idiomatic)
        // Kwargs are assembled into a Python dict and re-serialized via json so
        // serde_json can deserialize into the tagged enum.
        let json_str: String = if let Some(v) = value {
            if let Ok(s) = v.extract::<String>() {
                serde_json::to_string(&s).map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Invalid {{ name }}: {e}")))?
            } else {
                let json_mod = py.import("json")?;
                json_mod.call_method1("dumps", (v,))?.extract()?
            }
        } else if let Some(kw) = kwargs {
            let json_mod = py.import("json")?;
            json_mod.call_method1("dumps", (kw,))?.extract()?
        } else {
            return Err(pyo3::exceptions::PyTypeError::new_err(
                "{{ name }}() requires a positional value or keyword arguments".to_string(),
            ));
        };
        let inner: {{ core_path }} = serde_json::from_str(&json_str)
            .map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("Invalid {{ name }}: {e}")))?;
        Ok(Self { inner })
    }
{{ string_methods_content }}
{{ variant_accessors_content }}
{{ serde_tag_content }}
{%- endif %}
{%- if factory_methods_content %}
{{ factory_methods_content }}
{%- endif %}
}

impl From<{{ name }}> for {{ core_path }} {
    fn from(val: {{ name }}) -> Self { val.inner }
}

impl From<{{ core_path }}> for {{ name }} {
    fn from(val: {{ core_path }}) -> Self { Self { inner: val } }
}

impl serde::Serialize for {{ name }} {
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        self.inner.serialize(serializer)
    }
}

impl Default for {{ name }} {
    fn default() -> Self { Self { inner: Default::default() } }
}

impl<'de> serde::Deserialize<'de> for {{ name }} {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        let inner = {{ core_path }}::deserialize(deserializer)?;
        Ok(Self { inner })
    }
}