use std::str::FromStr;
use bindgen::ir::{Enum, Item};
#[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 => "",
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum RenameRule {
None,
GeckoCase,
LowerCase,
UpperCase,
PascalCase,
CamelCase,
SnakeCase,
ScreamingSnakeCase,
QualifiedScreamingSnakeCase,
}
impl RenameRule {
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 => {
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_lowercase() {
result.push(x);
}
}
result
}
RenameRule::ScreamingSnakeCase => {
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);
}
}
result
}
RenameRule::QualifiedScreamingSnakeCase => {
let mut result = String::new();
if let IdentifierType::EnumVariant(e) = context {
if let &RenameRule::QualifiedScreamingSnakeCase = self {
result.push_str(
&RenameRule::ScreamingSnakeCase
.apply_to_pascal_case(e.path().name(), IdentifierType::Enum),
);
result.push_str("_");
}
}
result
.push_str(&RenameRule::ScreamingSnakeCase.apply_to_pascal_case(&text, context));
result
}
}
}
pub fn apply_to_snake_case(&self, mut text: &str, context: IdentifierType) -> String {
if text.len() == 0 {
return String::new();
}
match *self {
RenameRule::None => String::from(text),
RenameRule::GeckoCase => {
if &text[..1] == "_" {
text = &text[1..];
}
context.to_str().to_owned()
+ &RenameRule::PascalCase.apply_to_snake_case(text, context)
}
RenameRule::LowerCase => text.to_lowercase(),
RenameRule::UpperCase => text.to_uppercase(),
RenameRule::PascalCase => {
let mut result = String::new();
let mut is_uppercase = true;
for c in text.chars() {
if c == '_' {
is_uppercase = true;
continue;
}
if is_uppercase {
for x in c.to_uppercase() {
result.push(x);
}
is_uppercase = false;
} else {
result.push(c);
}
}
result
}
RenameRule::CamelCase => {
let mut result = String::new();
let mut is_uppercase = false;
for c in text.chars() {
if c == '_' {
is_uppercase = true;
continue;
}
if is_uppercase {
for x in c.to_uppercase() {
result.push(x);
}
is_uppercase = false;
} else {
result.push(c);
}
}
result
}
RenameRule::SnakeCase => text.to_owned(),
RenameRule::ScreamingSnakeCase => text.to_owned().to_uppercase(),
RenameRule::QualifiedScreamingSnakeCase => {
let mut result = String::new();
if let IdentifierType::EnumVariant(e) = context {
if let &RenameRule::QualifiedScreamingSnakeCase = self {
result.push_str(
&RenameRule::ScreamingSnakeCase
.apply_to_snake_case(e.path().name(), IdentifierType::Enum),
);
result.push_str("_");
}
}
result
.push_str(&RenameRule::ScreamingSnakeCase.apply_to_snake_case(&text, context));
result
}
}
}
}
impl Default for RenameRule {
fn default() -> RenameRule {
RenameRule::None
}
}
impl FromStr for RenameRule {
type Err = String;
fn from_str(s: &str) -> Result<RenameRule, Self::Err> {
match s {
"none" => Ok(RenameRule::None),
"None" => Ok(RenameRule::None),
"mGeckoCase" => Ok(RenameRule::GeckoCase),
"GeckoCase" => Ok(RenameRule::GeckoCase),
"gecko_case" => Ok(RenameRule::GeckoCase),
"lowercase" => Ok(RenameRule::LowerCase),
"LowerCase" => Ok(RenameRule::LowerCase),
"lower_case" => Ok(RenameRule::LowerCase),
"UPPERCASE" => Ok(RenameRule::UpperCase),
"UpperCase" => Ok(RenameRule::UpperCase),
"upper_case" => Ok(RenameRule::UpperCase),
"PascalCase" => Ok(RenameRule::PascalCase),
"pascal_case" => Ok(RenameRule::PascalCase),
"camelCase" => Ok(RenameRule::CamelCase),
"CamelCase" => Ok(RenameRule::CamelCase),
"camel_case" => Ok(RenameRule::CamelCase),
"snake_case" => Ok(RenameRule::SnakeCase),
"SnakeCase" => Ok(RenameRule::SnakeCase),
"SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase),
"ScreamingSnakeCase" => Ok(RenameRule::ScreamingSnakeCase),
"screaming_snake_case" => Ok(RenameRule::ScreamingSnakeCase),
"QUALIFIED_SCREAMING_SNAKE_CASE" => Ok(RenameRule::QualifiedScreamingSnakeCase),
"QualifiedScreamingSnakeCase" => Ok(RenameRule::QualifiedScreamingSnakeCase),
"qualified_screaming_snake_case" => Ok(RenameRule::QualifiedScreamingSnakeCase),
_ => Err(format!("Unrecognized RenameRule: '{}'.", s)),
}
}
}
deserialize_enum_str!(RenameRule);