rulemorph 0.3.1

YAML-based declarative data transformation engine for CSV/JSON to JSON
Documentation
use std::collections::HashMap;

use crate::dto::DtoLanguage;

use super::{capitalize, lower_camel, pascal_case, snake_case, words_from_key};

mod reserved;

use self::reserved::is_reserved;

pub(in crate::dto) fn field_identifier(
    lang: DtoLanguage,
    key: &str,
    used: &mut HashMap<String, usize>,
) -> String {
    let base = match lang {
        DtoLanguage::Rust | DtoLanguage::Python => snake_case(&words_from_key(key)),
        DtoLanguage::TypeScript | DtoLanguage::Java | DtoLanguage::Kotlin | DtoLanguage::Swift => {
            lower_camel(&words_from_key(key))
        }
        DtoLanguage::Go => pascal_case(&words_from_key(key)),
    };

    let mut ident = if base.is_empty() {
        match lang {
            DtoLanguage::Go => "Field".to_string(),
            DtoLanguage::Java | DtoLanguage::Kotlin | DtoLanguage::Swift => "field".to_string(),
            _ => "field".to_string(),
        }
    } else {
        base
    };

    if ident
        .chars()
        .next()
        .map(|c| c.is_ascii_digit())
        .unwrap_or(true)
    {
        ident = match lang {
            DtoLanguage::Go => format!("Field{}", ident),
            DtoLanguage::Java | DtoLanguage::Kotlin | DtoLanguage::Swift => {
                format!("field{}", capitalize(&ident))
            }
            _ => format!("_{}", ident),
        };
    }

    if is_reserved(lang, &ident) {
        ident = match lang {
            DtoLanguage::Go => format!("{}Field", ident),
            _ => format!("{}_", ident),
        };
    }

    let entry = used.entry(ident.clone()).or_insert(0);
    if *entry > 0 {
        *entry += 1;
        format!("{}_{}", ident, *entry)
    } else {
        *entry = 1;
        ident
    }
}

pub(in crate::dto) fn safe_type_name(lang: DtoLanguage, name: &str) -> String {
    let words = words_from_key(name);
    let mut ident = pascal_case(&words);
    if ident.is_empty() {
        ident = "Record".to_string();
    }
    if ident
        .chars()
        .next()
        .map(|c| c.is_ascii_digit())
        .unwrap_or(true)
    {
        ident = format!("Record{}", ident);
    }
    if is_reserved(lang, &ident) {
        ident.push_str("Record");
    }
    ident
}