1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use std::borrow::Cow;
6use std::str::FromStr;
7
8/// The type of identifier to be renamed.
9#[derive(Debug, Clone, Copy)]
10pub enum IdentifierType<'a> {
11 StructMember,
12 EnumVariant { prefix: &'a str },
13 FunctionArg,
14 Type,
15 Enum,
16}
17
18impl<'a> IdentifierType<'a> {
19 fn to_str(self) -> &'static str {
20 match self {
21 IdentifierType::StructMember => "m",
22 IdentifierType::EnumVariant { .. } => "",
23 IdentifierType::FunctionArg => "a",
24 IdentifierType::Type => "",
25 IdentifierType::Enum => "",
26 }
27 }
28}
29
30/// A rule to apply to an identifier when generating bindings.
31#[derive(Debug, Clone, Copy, Default)]
32pub enum RenameRule {
33 /// Do not apply any renaming. The default.
34 #[default]
35 None,
36 /// Converts the identifier to PascalCase and adds a context dependent prefix
37 GeckoCase,
38 /// Converts the identifier to lower case.
39 LowerCase,
40 /// Converts the identifier to upper case.
41 UpperCase,
42 /// Converts the identifier to PascalCase.
43 PascalCase,
44 /// Converts the identifier to camelCase.
45 CamelCase,
46 /// Converts the identifier to snake_case.
47 SnakeCase,
48 /// Converts the identifier to SCREAMING_SNAKE_CASE.
49 ScreamingSnakeCase,
50 /// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants
51 /// with the enum name.
52 QualifiedScreamingSnakeCase,
53}
54
55impl RenameRule {
56 pub(crate) fn not_none(self) -> Option<Self> {
57 match self {
58 RenameRule::None => None,
59 other => Some(other),
60 }
61 }
62
63 /// Applies the rename rule to a string
64 pub fn apply<'a>(self, text: &'a str, context: IdentifierType) -> Cow<'a, str> {
65 use heck::*;
66
67 if text.is_empty() {
68 return Cow::Borrowed(text);
69 }
70
71 Cow::Owned(match self {
72 RenameRule::None => return Cow::Borrowed(text),
73 RenameRule::GeckoCase => context.to_str().to_owned() + &text.to_upper_camel_case(),
74 RenameRule::LowerCase => text.to_lowercase(),
75 RenameRule::UpperCase => text.to_uppercase(),
76 RenameRule::PascalCase => text.to_pascal_case(),
77 RenameRule::CamelCase => text.to_lower_camel_case(),
78 RenameRule::SnakeCase => text.to_snake_case(),
79 RenameRule::ScreamingSnakeCase => text.to_shouty_snake_case(),
80 RenameRule::QualifiedScreamingSnakeCase => {
81 let mut result = String::new();
82
83 if let IdentifierType::EnumVariant { prefix } = context {
84 result.push_str(
85 &RenameRule::ScreamingSnakeCase.apply(prefix, IdentifierType::Enum),
86 );
87 result.push('_');
88 }
89
90 result.push_str(&RenameRule::ScreamingSnakeCase.apply(text, context));
91 result
92 }
93 })
94 }
95}
96
97impl FromStr for RenameRule {
98 type Err = String;
99
100 fn from_str(s: &str) -> Result<RenameRule, Self::Err> {
101 match s {
102 "none" => Ok(RenameRule::None),
103 "None" => Ok(RenameRule::None),
104
105 "mGeckoCase" => Ok(RenameRule::GeckoCase),
106 "GeckoCase" => Ok(RenameRule::GeckoCase),
107 "gecko_case" => Ok(RenameRule::GeckoCase),
108
109 "lowercase" => Ok(RenameRule::LowerCase),
110 "LowerCase" => Ok(RenameRule::LowerCase),
111 "lower_case" => Ok(RenameRule::LowerCase),
112
113 "UPPERCASE" => Ok(RenameRule::UpperCase),
114 "UpperCase" => Ok(RenameRule::UpperCase),
115 "upper_case" => Ok(RenameRule::UpperCase),
116
117 "PascalCase" => Ok(RenameRule::PascalCase),
118 "pascal_case" => Ok(RenameRule::PascalCase),
119
120 "camelCase" => Ok(RenameRule::CamelCase),
121 "CamelCase" => Ok(RenameRule::CamelCase),
122 "camel_case" => Ok(RenameRule::CamelCase),
123
124 "snake_case" => Ok(RenameRule::SnakeCase),
125 "SnakeCase" => Ok(RenameRule::SnakeCase),
126
127 "SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase),
128 "ScreamingSnakeCase" => Ok(RenameRule::ScreamingSnakeCase),
129 "screaming_snake_case" => Ok(RenameRule::ScreamingSnakeCase),
130
131 "QUALIFIED_SCREAMING_SNAKE_CASE" => Ok(RenameRule::QualifiedScreamingSnakeCase),
132 "QualifiedScreamingSnakeCase" => Ok(RenameRule::QualifiedScreamingSnakeCase),
133 "qualified_screaming_snake_case" => Ok(RenameRule::QualifiedScreamingSnakeCase),
134
135 _ => Err(format!("Unrecognized RenameRule: '{}'.", s)),
136 }
137 }
138}
139
140deserialize_enum_str!(RenameRule);
141