simploxide-bindgen 0.4.0

SimpleX-Chat API types and client generator
Documentation
use super::TopLevelDocs;

use convert_case::{Case, Casing as _};
use std::str::FromStr;

pub struct EnumType {
    pub name: String,
    pub variants: Vec<EnumVariant>,
    pub doc_comments: Vec<String>,
    pub syntax: String,
}

impl EnumType {
    pub fn new(name: String, variants: Vec<EnumVariant>) -> Self {
        Self {
            name,
            variants,
            doc_comments: Vec::new(),
            syntax: String::new(),
        }
    }
}

impl TopLevelDocs for EnumType {
    fn doc_lines(&self) -> &Vec<String> {
        &self.doc_comments
    }

    fn syntax(&self) -> &str {
        self.syntax.as_str()
    }
}

impl std::fmt::Display for EnumType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.write_docs_fmt(f)?;

        writeln!(
            f,
            "#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]"
        )?;
        writeln!(f, "#[non_exhaustive]")?;
        writeln!(f, "pub enum {} {{", self.name)?;
        writeln!(f, "    #[default]")?;

        for var in &self.variants {
            writeln!(f, "    #[serde(rename = \"{}\")]", var.api_name)?;
            writeln!(f, "    {},", var.rust_name)?;
        }

        writeln!(f, "}}")
    }
}

pub struct EnumVariant {
    pub api_name: String,
    pub rust_name: String,
}

impl EnumVariant {
    pub fn from_api_name(api_name: &str) -> Self {
        Self {
            api_name: api_name.to_owned(),
            rust_name: api_name.remove_empty().to_case(Case::Pascal),
        }
    }
}

impl FromStr for EnumVariant {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if !s.starts_with('"') || !s.ends_with('"') {
            return Err(format!("'{s}' is not an enum variant name"));
        }

        let api_name = s.trim_matches('"').to_owned();
        let rust_name = api_name.remove_empty().to_case(Case::Pascal);

        Ok(Self {
            api_name,
            rust_name,
        })
    }
}