tsain-pattern 0.1.0

Chain TypeScript and Rust in fast and secure way
Documentation
use super::*;

/// None for skipped enum
/// Some((var-ts-name (without enum prefix), var props pattern))
pub type EnumPattern = Composition<Vec<Option<(&'static str, PropsPattern)>>>;

impl EnumPattern {
    pub fn list(&self) -> &Vec<Option<(&'static str, PropsPattern)>> {
        &self.list
    }

    fn union_script(&self) -> String {
        let ts_name = &self.ts_name;
        let type_args = crate::format_type_args(&self.type_args);
        let var_names = self
            .list
            .iter()
            .filter_map(|var| {
                var.as_ref().map(|(_, var)| {
                    format!(
                        "{}{}",
                        var.ts_name,
                        &crate::format_type_args(&var.type_args),
                    )
                })
            })
            .collect::<Vec<_>>()
            .join(" | ");

        // NOTE: enum itself should not have brand
        format!(r#"export type {ts_name}{type_args} = {var_names};"#)
    }

    fn var_ids_script(&self) -> String {
        self.list
            .iter()
            .enumerate()
            .filter_map(|(var_id, var)| {
                var.as_ref().map(|(_, var)| {
                    let var_ts_name = &var.ts_name;
                    format!("export const {var_ts_name}Id: number = {var_id};")
                })
            })
            .collect::<Vec<_>>()
            .join("\n")
    }

    fn vars_script(&self, props_formatter: &impl PropsFormatter) -> String {
        self.list
            .iter()
            .enumerate()
            .filter_map(|(var_id, var)| {
                let (_, var) = var.as_ref()?;
                Some(props_formatter.format_type_script(var, Some(var_id as u32)))
            })
            .collect::<Vec<_>>()
            .join("\n")
    }

    fn as_vars_script(&self, props_formatter: &impl PropsFormatter) -> String {
        self.list
            .iter()
            .enumerate()
            .filter_map(|(var_id, var)| {
                let (_, var) = var.as_ref()?;
                let script = props_formatter.as_variant_script(
                    var,
                    self.ts_name,
                    &crate::format_type_args(&self.type_args),
                    var_id as u32,
                );
                Some(script)
            })
            .collect::<Vec<_>>()
            .join("\n")
    }

    pub(super) fn format_enum_type_script(&self, props_formatter: &impl PropsFormatter) -> String {
        crate::formatter::format_script(
            format!("// # Enum {}", &self.ts_name),
            vec![
                (
                    // 1. Union
                    String::new(),
                    self.union_script(),
                ),
                (
                    // 2. Var Ids
                    format!("// ## Var Ids"),
                    self.var_ids_script(),
                ),
                (
                    // 3. As Each Vars
                    format!("// ## As Each Var"),
                    self.as_vars_script(props_formatter),
                ),
                (
                    // 4. Each Vars
                    format!(""),
                    self.vars_script(props_formatter),
                ),
            ],
        )
    }
}