use crate::types::RenameAll;
impl RenameAll {
pub fn apply_to_field(self, field: &str) -> String {
match self {
Self::Lowercase | Self::SnakeCase => field.to_owned(),
Self::Uppercase => field.to_ascii_uppercase(),
Self::PascalCase => snake_to_pascal(field),
Self::CamelCase => {
let pascal = snake_to_pascal(field);
lowercase_first_char(&pascal)
}
Self::ScreamingSnakeCase => field.to_ascii_uppercase(),
Self::KebabCase => field.replace('_', "-"),
Self::ScreamingKebabCase => field.to_ascii_uppercase().replace('_', "-"),
}
}
pub fn apply_to_variant(self, variant: &str) -> String {
match self {
Self::PascalCase => variant.to_owned(),
Self::Lowercase => variant.to_ascii_lowercase(),
Self::Uppercase => variant.to_ascii_uppercase(),
Self::CamelCase => lowercase_first_char(variant),
Self::SnakeCase => pascal_to_snake(variant),
Self::ScreamingSnakeCase => pascal_to_snake(variant).to_ascii_uppercase(),
Self::KebabCase => pascal_to_snake(variant).replace('_', "-"),
Self::ScreamingKebabCase => pascal_to_snake(variant).to_ascii_uppercase().replace('_', "-"),
}
}
}
fn snake_to_pascal(snake: &str) -> String {
let mut out = String::with_capacity(snake.len());
let mut capitalize_next = true;
for ch in snake.chars() {
if ch == '_' {
capitalize_next = true;
} else if capitalize_next {
out.push(ch.to_ascii_uppercase());
capitalize_next = false;
} else {
out.push(ch);
}
}
out
}
fn pascal_to_snake(pascal: &str) -> String {
let mut out = String::with_capacity(pascal.len() + 4);
for (i, ch) in pascal.char_indices() {
if i > 0 && ch.is_ascii_uppercase() {
out.push('_');
}
out.push(ch.to_ascii_lowercase());
}
out
}
fn lowercase_first_char(s: &str) -> String {
let mut chars = s.chars();
match chars.next() {
Some(first) => {
let mut out = String::with_capacity(s.len());
out.push(first.to_ascii_lowercase());
out.extend(chars);
out
}
None => String::new(),
}
}
#[cfg(test)]
mod tests {
use crate::types::RenameAll;
#[test]
fn field_lowercase_is_identity() {
assert_eq!(RenameAll::Lowercase.apply_to_field("parse_url_v2"), "parse_url_v2");
}
#[test]
fn field_snake_case_is_identity() {
assert_eq!(RenameAll::SnakeCase.apply_to_field("parse_url_v2"), "parse_url_v2");
}
#[test]
fn field_uppercase() {
assert_eq!(RenameAll::Uppercase.apply_to_field("parse_url_v2"), "PARSE_URL_V2");
}
#[test]
fn field_pascal_case() {
assert_eq!(RenameAll::PascalCase.apply_to_field("parse_url_v2"), "ParseUrlV2");
assert_eq!(RenameAll::PascalCase.apply_to_field("html_parser"), "HtmlParser");
assert_eq!(RenameAll::PascalCase.apply_to_field("single"), "Single");
}
#[test]
fn field_camel_case() {
assert_eq!(RenameAll::CamelCase.apply_to_field("parse_url_v2"), "parseUrlV2");
assert_eq!(RenameAll::CamelCase.apply_to_field("html_parser"), "htmlParser");
assert_eq!(RenameAll::CamelCase.apply_to_field("single"), "single");
}
#[test]
fn field_screaming_snake_case() {
assert_eq!(RenameAll::ScreamingSnakeCase.apply_to_field("parse_url_v2"), "PARSE_URL_V2");
}
#[test]
fn field_kebab_case() {
assert_eq!(RenameAll::KebabCase.apply_to_field("parse_url_v2"), "parse-url-v2");
}
#[test]
fn field_screaming_kebab_case() {
assert_eq!(RenameAll::ScreamingKebabCase.apply_to_field("parse_url_v2"), "PARSE-URL-V2");
}
#[test]
fn variant_pascal_case_is_identity() {
assert_eq!(RenameAll::PascalCase.apply_to_variant("ApiClient"), "ApiClient");
}
#[test]
fn variant_lowercase() {
assert_eq!(RenameAll::Lowercase.apply_to_variant("ApiClient"), "apiclient");
}
#[test]
fn variant_uppercase() {
assert_eq!(RenameAll::Uppercase.apply_to_variant("ApiClient"), "APICLIENT");
}
#[test]
fn variant_camel_case() {
assert_eq!(RenameAll::CamelCase.apply_to_variant("ApiClient"), "apiClient");
assert_eq!(RenameAll::CamelCase.apply_to_variant("HTMLParser"), "hTMLParser");
}
#[test]
fn variant_snake_case() {
assert_eq!(RenameAll::SnakeCase.apply_to_variant("ApiClient"), "api_client");
assert_eq!(RenameAll::SnakeCase.apply_to_variant("HTMLParser"), "h_t_m_l_parser");
assert_eq!(RenameAll::SnakeCase.apply_to_variant("Single"), "single");
}
#[test]
fn variant_screaming_snake_case() {
assert_eq!(RenameAll::ScreamingSnakeCase.apply_to_variant("ApiClient"), "API_CLIENT");
assert_eq!(RenameAll::ScreamingSnakeCase.apply_to_variant("HTMLParser"), "H_T_M_L_PARSER");
}
#[test]
fn variant_kebab_case() {
assert_eq!(RenameAll::KebabCase.apply_to_variant("ApiClient"), "api-client");
}
#[test]
fn variant_screaming_kebab_case() {
assert_eq!(RenameAll::ScreamingKebabCase.apply_to_variant("ApiClient"), "API-CLIENT");
}
#[test]
fn empty_input_pass_through() {
for mode in [
RenameAll::Lowercase,
RenameAll::Uppercase,
RenameAll::PascalCase,
RenameAll::CamelCase,
RenameAll::SnakeCase,
RenameAll::ScreamingSnakeCase,
RenameAll::KebabCase,
RenameAll::ScreamingKebabCase,
] {
assert_eq!(mode.apply_to_field(""), "");
assert_eq!(mode.apply_to_variant(""), "");
}
}
#[test]
fn field_with_digit_segment_camel_case() {
assert_eq!(RenameAll::PascalCase.apply_to_field("parse_v2"), "ParseV2");
assert_eq!(RenameAll::CamelCase.apply_to_field("parse_v2"), "parseV2");
}
}