tyzen-macro 0.2.2

Procedural macros for the tyzen crate.
Documentation
#[derive(Clone, Copy)]
pub enum RenameRule {
    Lowercase,
    Uppercase,
    PascalCase,
    CamelCase,
    SnakeCase,
    ScreamingSnakeCase,
    KebabCase,
    ScreamingKebabCase,
}

pub fn rename_rule(rule: &str) -> Option<RenameRule> {
    Some(match rule {
        "lowercase" => RenameRule::Lowercase,
        "UPPERCASE" => RenameRule::Uppercase,
        "PascalCase" => RenameRule::PascalCase,
        "camelCase" => RenameRule::CamelCase,
        "snake_case" => RenameRule::SnakeCase,
        "SCREAMING_SNAKE_CASE" => RenameRule::ScreamingSnakeCase,
        "kebab-case" => RenameRule::KebabCase,
        "SCREAMING-KEBAB-CASE" => RenameRule::ScreamingKebabCase,
        _ => return None,
    })
}

pub fn apply_rename_rule(name: &str, rule: RenameRule) -> String {
    let words = get_words(name);

    match rule {
        RenameRule::Lowercase => words.join("").to_lowercase(),
        RenameRule::Uppercase => words.join("").to_uppercase(),
        RenameRule::PascalCase => words.iter().map(|word| capitalize(word)).collect(),
        RenameRule::CamelCase => {
            let mut out = String::new();
            for (index, word) in words.iter().enumerate() {
                if index == 0 {
                    out.push_str(&word.to_lowercase());
                } else {
                    out.push_str(&capitalize(word));
                }
            }
            out
        }
        RenameRule::SnakeCase => words.join("_").to_lowercase(),
        RenameRule::ScreamingSnakeCase => words.join("_").to_uppercase(),
        RenameRule::KebabCase => words.join("-").to_lowercase(),
        RenameRule::ScreamingKebabCase => words.join("-").to_uppercase(),
    }
}

fn get_words(name: &str) -> Vec<String> {
    let mut words = Vec::new();
    let mut current = String::new();

    for ch in name.chars() {
        if ch == '_' || ch == '-' {
            if !current.is_empty() {
                words.push(std::mem::take(&mut current));
            }
            continue;
        }

        if ch.is_uppercase() && !current.is_empty() {
            words.push(std::mem::take(&mut current));
        }

        current.push(ch);
    }

    if !current.is_empty() {
        words.push(current);
    }

    words
}

fn capitalize(word: &str) -> String {
    let mut chars = word.chars();
    match chars.next() {
        Some(first) => first.to_uppercase().collect::<String>() + &chars.as_str().to_lowercase(),
        None => String::new(),
    }
}