<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::str::FromStr;

use bindgen::ir::{Enum, Item};

/// The type of identifier to be renamed.
#[derive(Debug, Clone, Copy)]
pub enum IdentifierType<'a> {
    StructMember,
    EnumVariant(&'a Enum),
    FunctionArg,
    Enum,
}

impl<'a> IdentifierType<'a> {
    fn to_str(&'a self) -> &'static str {
        match *self {
            IdentifierType::StructMember => "m",
            IdentifierType::EnumVariant(..) => "",
            IdentifierType::FunctionArg => "a",
            IdentifierType::Enum => "",
        }
    }
}

/// A rule to apply to an identifier when generating bindings.
#[derive(Debug, Clone, Copy)]
pub enum RenameRule {
    /// Do not apply any renaming. The default.
    None,
    /// Converts the identifier to PascalCase and adds a context dependent prefix
    GeckoCase,
    /// Converts the identifier to lower case.
    LowerCase,
    /// Converts the identifier to upper case.
    UpperCase,
    /// Converts the identifier to PascalCase.
    PascalCase,
    /// Converts the identifier to camelCase.
    CamelCase,
    /// Converts the identifier to snake_case.
    SnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE.
    ScreamingSnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants
    /// with the enum name.
    QualifiedScreamingSnakeCase,
}

impl RenameRule {
    /// Applies the rename rule to a string that is formatted in PascalCase.
    pub fn apply_to_pascal_case(&self, text: &str, context: IdentifierType) -> String {
        if text.len() == 0 {
            return String::new();
        }

        match *self {
            RenameRule::None => String::from(text),
            RenameRule::GeckoCase => context.to_str().to_owned() + text,
            RenameRule::LowerCase => text.to_lowercase(),
            RenameRule::UpperCase => text.to_uppercase(),
            RenameRule::PascalCase => text.to_owned(),
            RenameRule::CamelCase => text[..1].to_lowercase() + &text[1..],
            RenameRule::SnakeCase => {
                // Do not add additional `_` if the string already contains `_` e.g. `__Field`
                // Do not split consecutive capital letters
                let mut result = String::new();
                let mut add_separator = true;
                let mut prev_uppercase = false;
                for (i, c) in text.char_indices() {
                    if c == '_' {
                        add_separator = false;
                        prev_uppercase = false;
                    }
                    if c.is_uppercase() {
                        if i != 0 && add_separator && !prev_uppercase {
                            result.push_str("_");
                        } else {
                            add_separator = true;
                        }
                        prev_uppercase = true;
                    } else {
                        prev_uppercase = false;
                    }
                    for x in c.to_lowercase() {
                        result.push(x);
                    }
                }
                result
            }
            RenameRule::ScreamingSnakeCase => {
                // Same as SnakeCase code above, but uses to_uppercase
                let mut result = String::new();
                for (i, c) in text.char_indices() {
                    if c.is_uppercase() && i != 0 {
                        result.push_str("_");
                    }
                    for x in c.to_uppercase() {
                        result.push(x);<commit_msg>Make the ScreamingSnakeCase formatter behave as the SnakeCase one<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::str::FromStr;

use bindgen::ir::{Enum, Item};

/// The type of identifier to be renamed.
#[derive(Debug, Clone, Copy)]
pub enum IdentifierType<'a> {
    StructMember,
    EnumVariant(&'a Enum),
    FunctionArg,
    Enum,
}

impl<'a> IdentifierType<'a> {
    fn to_str(&'a self) -> &'static str {
        match *self {
            IdentifierType::StructMember => "m",
            IdentifierType::EnumVariant(..) => "",
            IdentifierType::FunctionArg => "a",
            IdentifierType::Enum => "",
        }
    }
}

/// A rule to apply to an identifier when generating bindings.
#[derive(Debug, Clone, Copy)]
pub enum RenameRule {
    /// Do not apply any renaming. The default.
    None,
    /// Converts the identifier to PascalCase and adds a context dependent prefix
    GeckoCase,
    /// Converts the identifier to lower case.
    LowerCase,
    /// Converts the identifier to upper case.
    UpperCase,
    /// Converts the identifier to PascalCase.
    PascalCase,
    /// Converts the identifier to camelCase.
    CamelCase,
    /// Converts the identifier to snake_case.
    SnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE.
    ScreamingSnakeCase,
    /// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants
    /// with the enum name.
    QualifiedScreamingSnakeCase,
}

impl RenameRule {
    /// Applies the rename rule to a string that is formatted in PascalCase.
    pub fn apply_to_pascal_case(&self, text: &str, context: IdentifierType) -> String {
        if text.len() == 0 {
            return String::new();
        }

        match *self {
            RenameRule::None => String::from(text),
            RenameRule::GeckoCase => context.to_str().to_owned() + text,
            RenameRule::LowerCase => text.to_lowercase(),
            RenameRule::UpperCase => text.to_uppercase(),
            RenameRule::PascalCase => text.to_owned(),
            RenameRule::CamelCase => text[..1].to_lowercase() + &text[1..],
            RenameRule::SnakeCase => {
                // Do not add additional `_` if the string already contains `_` e.g. `__Field`
                // Do not split consecutive capital letters
                let mut result = String::new();
                let mut add_separator = true;
                let mut prev_uppercase = false;
                for (i, c) in text.char_indices() {
                    if c == '_' {
                        add_separator = false;
                        prev_uppercase = false;
                    }
                    if c.is_uppercase() {
                        if i != 0 && add_separator && !prev_uppercase {
                            result.push_str("_");
                        } else {
                            add_separator = true;
                        }
                        prev_uppercase = true;
                    } else {
                        prev_uppercase = false;
                    }
                    for x in c.to_lowercase() {
                        result.push(x);
                    }
                }
                result
            }
            RenameRule::ScreamingSnakeCase => {
                // Same as SnakeCase code above, but uses to_uppercase
                let mut result = String::new();
                let mut add_separator = true;
                let mut prev_uppercase = false;
                for (i, c) in text.char_indices() {
                    if c == '_' {
                        add_separator = false;
                        prev_uppercase = false;
                    }
                    if c.is_uppercase() {
                        if i != 0 && add_separator && !prev_uppercase {
                            result.push_str("_");
                        } else {
                            add_separator = true;
                        }
                        prev_uppercase = true;
                    } else {
                        prev_uppercase = false;
                    }
                    for x in c.to_uppercase() {
                        result.push(x);
{'fraction_non_alphanumeric': 0.10078566167444145, 'fraction_numerical': 0.00220967345936656, 'mean_word_length': 1.4657990314769975, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '621335', 'n_tokens_mistral': 2230, 'n_tokens_neox': 2118, 'n_words': 622}