cbindgen/bindgen/
rename.rs

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);