alef-codegen 0.3.4

Shared codegen utilities for the alef polyglot binding generator
Documentation
use alef_core::ir::EnumDef;
use std::fmt::Write;

use super::ConversionConfig;
use super::helpers::{binding_to_core_match_arm_ext, core_enum_path, core_to_binding_match_arm_ext};

/// Generate `impl From<BindingEnum> for core::Enum` (binding -> core).
pub fn gen_enum_from_binding_to_core(enum_def: &EnumDef, core_import: &str) -> String {
    gen_enum_from_binding_to_core_cfg(enum_def, core_import, &ConversionConfig::default())
}

/// Generate `impl From<BindingEnum> for core::Enum` with backend-specific config.
pub fn gen_enum_from_binding_to_core_cfg(enum_def: &EnumDef, core_import: &str, config: &ConversionConfig) -> String {
    let core_path = core_enum_path(enum_def, core_import);
    let binding_name = format!("{}{}", config.type_name_prefix, enum_def.name);
    let mut out = String::with_capacity(256);
    writeln!(out, "impl From<{binding_name}> for {core_path} {{").ok();
    writeln!(out, "    fn from(val: {binding_name}) -> Self {{").ok();
    writeln!(out, "        match val {{").ok();
    for variant in &enum_def.variants {
        let arm = binding_to_core_match_arm_ext(
            &binding_name,
            &variant.name,
            &variant.fields,
            config.binding_enums_have_data,
        );
        writeln!(out, "            {arm}").ok();
    }
    writeln!(out, "        }}").ok();
    writeln!(out, "    }}").ok();
    write!(out, "}}").ok();
    out
}

/// Generate `impl From<core::Enum> for BindingEnum` (core -> binding).
pub fn gen_enum_from_core_to_binding(enum_def: &EnumDef, core_import: &str) -> String {
    gen_enum_from_core_to_binding_cfg(enum_def, core_import, &ConversionConfig::default())
}

/// Generate `impl From<core::Enum> for BindingEnum` with backend-specific config.
pub fn gen_enum_from_core_to_binding_cfg(enum_def: &EnumDef, core_import: &str, config: &ConversionConfig) -> String {
    let core_path = core_enum_path(enum_def, core_import);
    let binding_name = format!("{}{}", config.type_name_prefix, enum_def.name);
    let mut out = String::with_capacity(256);
    writeln!(out, "impl From<{core_path}> for {binding_name} {{").ok();
    writeln!(out, "    fn from(val: {core_path}) -> Self {{").ok();
    writeln!(out, "        match val {{").ok();
    for variant in &enum_def.variants {
        let arm = core_to_binding_match_arm_ext(
            &core_path,
            &variant.name,
            &variant.fields,
            config.binding_enums_have_data,
        );
        writeln!(out, "            {arm}").ok();
    }
    writeln!(out, "        }}").ok();
    writeln!(out, "    }}").ok();
    write!(out, "}}").ok();
    out
}