From 330774a5f392e09741be0b6f46928a8909bb3946 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 3 Oct 2024 18:54:35 -0700 Subject: [PATCH 1/3] Add rename-all=prefix: This adds a new rename-all annotation which allows setting a specific prefix to all fields. For example: ```rust /// cbindgen:rename-all=prefix:ERR_ enum Error { Bad = 0, VeryBad = 1 } ``` While in principle this can be added to the config file, it's primarily useful for overrides on a case-by-case basis. --- src/bindgen/ir/enumeration.rs | 4 ++-- src/bindgen/ir/function.rs | 2 +- src/bindgen/ir/structure.rs | 2 +- src/bindgen/ir/union.rs | 2 +- src/bindgen/mangle.rs | 2 ++ src/bindgen/rename.rs | 12 ++++++++++-- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index d6ec313a9..e649b49a3 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -154,7 +154,7 @@ impl EnumVariant { let body_rule = enum_annotations .parse_atom::("rename-variant-name-fields") - .unwrap_or(config.enumeration.rename_variant_name_fields); + .unwrap_or(config.enumeration.rename_variant_name_fields.clone()); let body = match variant.fields { syn::Fields::Unit => VariantBody::Empty(annotations), @@ -558,7 +558,7 @@ impl Item for Enum { let rules = self .annotations .parse_atom::("rename-all") - .unwrap_or(config.enumeration.rename_variants); + .unwrap_or(config.enumeration.rename_variants.clone()); if let Some(r) = rules.not_none() { self.variants = self diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index 79adfce94..99d926746 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -159,7 +159,7 @@ impl Function { let rules = self .annotations .parse_atom::("rename-all") - .unwrap_or(config.function.rename_args); + .unwrap_or(config.function.rename_args.clone()); if let Some(r) = rules.not_none() { let args = std::mem::take(&mut self.args); diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 9b33a15c7..fe71d22c6 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -342,7 +342,7 @@ impl Item for Struct { let field_rules = self .annotations .parse_atom::("rename-all") - .unwrap_or(config.structure.rename_fields); + .unwrap_or(config.structure.rename_fields.clone()); if let Some(o) = self.annotations.list("field-names") { for (dest, src) in names.zip(o) { diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index 410e21a27..fb47a1efa 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -171,7 +171,7 @@ impl Item for Union { let rules = self .annotations .parse_atom::("rename-all") - .unwrap_or(config.structure.rename_fields); + .unwrap_or(config.structure.rename_fields.clone()); if let Some(o) = self.annotations.list("field-names") { let mut overriden_fields = Vec::new(); diff --git a/src/bindgen/mangle.rs b/src/bindgen/mangle.rs index 52c3be93e..c5de0c8c9 100644 --- a/src/bindgen/mangle.rs +++ b/src/bindgen/mangle.rs @@ -93,6 +93,7 @@ impl<'a> Mangler<'a> { &self .config .rename_types + .clone() .apply(&sub_path, IdentifierType::Type), ); } @@ -101,6 +102,7 @@ impl<'a> Mangler<'a> { &self .config .rename_types + .clone() .apply(primitive.to_repr_rust(), IdentifierType::Type), ); } diff --git a/src/bindgen/rename.rs b/src/bindgen/rename.rs index f594939e8..aa40b68ba 100644 --- a/src/bindgen/rename.rs +++ b/src/bindgen/rename.rs @@ -28,7 +28,7 @@ impl<'a> IdentifierType<'a> { } /// A rule to apply to an identifier when generating bindings. -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Default)] pub enum RenameRule { /// Do not apply any renaming. The default. #[default] @@ -50,6 +50,8 @@ pub enum RenameRule { /// Converts the identifier to SCREAMING_SNAKE_CASE and prefixes enum variants /// with the enum name. QualifiedScreamingSnakeCase, + /// Adds a given prefix + Prefix(String), } impl RenameRule { @@ -61,7 +63,7 @@ impl RenameRule { } /// Applies the rename rule to a string - pub fn apply<'a>(self, text: &'a str, context: IdentifierType) -> Cow<'a, str> { + pub fn apply<'a>(&self, text: &'a str, context: IdentifierType) -> Cow<'a, str> { use heck::*; if text.is_empty() { @@ -90,6 +92,7 @@ impl RenameRule { result.push_str(&RenameRule::ScreamingSnakeCase.apply(text, context)); result } + RenameRule::Prefix(prefix) => prefix.to_owned() + text, }) } } @@ -98,6 +101,9 @@ impl FromStr for RenameRule { type Err = String; fn from_str(s: &str) -> Result { + const PREFIX: &str = "prefix:"; + const PREFIX_LEN: usize = PREFIX.len(); + match s { "none" => Ok(RenameRule::None), "None" => Ok(RenameRule::None), @@ -132,6 +138,8 @@ impl FromStr for RenameRule { "QualifiedScreamingSnakeCase" => Ok(RenameRule::QualifiedScreamingSnakeCase), "qualified_screaming_snake_case" => Ok(RenameRule::QualifiedScreamingSnakeCase), + s if s.starts_with(PREFIX) => Ok(RenameRule::Prefix(s[PREFIX_LEN..].to_string())), + _ => Err(format!("Unrecognized RenameRule: '{}'.", s)), } } From 61d484fc4fec62e669d97304e01fb0e42efc89d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 27 Oct 2024 23:17:16 +0100 Subject: [PATCH 2/3] Less clone for rename-all. --- src/bindgen/ir/enumeration.rs | 15 ++++++++------- src/bindgen/ir/function.rs | 6 ++---- src/bindgen/ir/structure.rs | 8 ++++---- src/bindgen/ir/union.rs | 6 ++---- src/bindgen/mangle.rs | 2 -- src/bindgen/rename.rs | 2 +- 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index e649b49a3..8927b8be5 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -152,9 +152,10 @@ impl EnumVariant { annotations.add_default("derive-ostream", AnnotationValue::Bool(b)); } - let body_rule = enum_annotations - .parse_atom::("rename-variant-name-fields") - .unwrap_or(config.enumeration.rename_variant_name_fields.clone()); + let body_rule = enum_annotations.parse_atom::("rename-variant-name-fields"); + let body_rule = body_rule + .as_ref() + .unwrap_or(&config.enumeration.rename_variant_name_fields); let body = match variant.fields { syn::Fields::Unit => VariantBody::Empty(annotations), @@ -555,10 +556,10 @@ impl Item for Enum { } } - let rules = self - .annotations - .parse_atom::("rename-all") - .unwrap_or(config.enumeration.rename_variants.clone()); + let rules = self.annotations.parse_atom::("rename-all"); + let rules = rules + .as_ref() + .unwrap_or(&config.enumeration.rename_variants); if let Some(r) = rules.not_none() { self.variants = self diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index 99d926746..f25d2f884 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -156,10 +156,8 @@ impl Function { self.ret.rename_for_config(config, &generic_params); // Apply rename rules to argument names - let rules = self - .annotations - .parse_atom::("rename-all") - .unwrap_or(config.function.rename_args.clone()); + let rules = self.annotations.parse_atom::("rename-all"); + let rules = rules.as_ref().unwrap_or(&config.function.rename_args); if let Some(r) = rules.not_none() { let args = std::mem::take(&mut self.args); diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index fe71d22c6..d805d69c9 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -339,10 +339,10 @@ impl Item for Struct { { let names = self.fields.iter_mut().map(|field| &mut field.name); - let field_rules = self - .annotations - .parse_atom::("rename-all") - .unwrap_or(config.structure.rename_fields.clone()); + let field_rules = self.annotations.parse_atom::("rename-all"); + let field_rules = field_rules + .as_ref() + .unwrap_or(&config.structure.rename_fields); if let Some(o) = self.annotations.list("field-names") { for (dest, src) in names.zip(o) { diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index fb47a1efa..9c4258372 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -168,10 +168,8 @@ impl Item for Union { field.ty.rename_for_config(config, &self.generic_params); } - let rules = self - .annotations - .parse_atom::("rename-all") - .unwrap_or(config.structure.rename_fields.clone()); + let rules = self.annotations.parse_atom::("rename-all"); + let rules = rules.as_ref().unwrap_or(&config.structure.rename_fields); if let Some(o) = self.annotations.list("field-names") { let mut overriden_fields = Vec::new(); diff --git a/src/bindgen/mangle.rs b/src/bindgen/mangle.rs index c5de0c8c9..52c3be93e 100644 --- a/src/bindgen/mangle.rs +++ b/src/bindgen/mangle.rs @@ -93,7 +93,6 @@ impl<'a> Mangler<'a> { &self .config .rename_types - .clone() .apply(&sub_path, IdentifierType::Type), ); } @@ -102,7 +101,6 @@ impl<'a> Mangler<'a> { &self .config .rename_types - .clone() .apply(primitive.to_repr_rust(), IdentifierType::Type), ); } diff --git a/src/bindgen/rename.rs b/src/bindgen/rename.rs index aa40b68ba..6f4928ef7 100644 --- a/src/bindgen/rename.rs +++ b/src/bindgen/rename.rs @@ -55,7 +55,7 @@ pub enum RenameRule { } impl RenameRule { - pub(crate) fn not_none(self) -> Option { + pub(crate) fn not_none(&self) -> Option<&Self> { match self { RenameRule::None => None, other => Some(other), From 99ccfac1be4beb3226d6ad32af5b7e2fc2db1b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 27 Oct 2024 23:18:33 +0100 Subject: [PATCH 3/3] rename: Add a test for rename-all=prefix: --- tests/expectations/rename_case.c | 2 ++ tests/expectations/rename_case.compat.c | 2 ++ tests/expectations/rename_case.cpp | 2 ++ tests/expectations/rename_case.pyx | 2 ++ tests/rust/rename_case.rs | 4 ++++ 5 files changed, 12 insertions(+) diff --git a/tests/expectations/rename_case.c b/tests/expectations/rename_case.c index c57482319..027645666 100644 --- a/tests/expectations/rename_case.c +++ b/tests/expectations/rename_case.c @@ -12,3 +12,5 @@ void test_snake_case(int32_t foo_bar); void test_screaming_snake_case(int32_t FOO_BAR); void test_gecko_case(int32_t aFooBar); + +void test_prefix(int32_t prefix_foo_bar); diff --git a/tests/expectations/rename_case.compat.c b/tests/expectations/rename_case.compat.c index 1d2cb1c59..ba66eeee8 100644 --- a/tests/expectations/rename_case.compat.c +++ b/tests/expectations/rename_case.compat.c @@ -17,6 +17,8 @@ void test_screaming_snake_case(int32_t FOO_BAR); void test_gecko_case(int32_t aFooBar); +void test_prefix(int32_t prefix_foo_bar); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/tests/expectations/rename_case.cpp b/tests/expectations/rename_case.cpp index 0d5a6d949..c87cfbf78 100644 --- a/tests/expectations/rename_case.cpp +++ b/tests/expectations/rename_case.cpp @@ -16,4 +16,6 @@ void test_screaming_snake_case(int32_t FOO_BAR); void test_gecko_case(int32_t aFooBar); +void test_prefix(int32_t prefix_foo_bar); + } // extern "C" diff --git a/tests/expectations/rename_case.pyx b/tests/expectations/rename_case.pyx index 5fd35fc4c..a78178230 100644 --- a/tests/expectations/rename_case.pyx +++ b/tests/expectations/rename_case.pyx @@ -15,3 +15,5 @@ cdef extern from *: void test_screaming_snake_case(int32_t FOO_BAR); void test_gecko_case(int32_t aFooBar); + + void test_prefix(int32_t prefix_foo_bar); diff --git a/tests/rust/rename_case.rs b/tests/rust/rename_case.rs index e83227d02..d01b71e67 100644 --- a/tests/rust/rename_case.rs +++ b/tests/rust/rename_case.rs @@ -17,3 +17,7 @@ pub extern "C" fn test_screaming_snake_case(foo_bar: i32) {} /// cbindgen:rename-all=GeckoCase #[no_mangle] pub extern "C" fn test_gecko_case(foo_bar: i32) {} + +/// cbindgen:rename-all=prefix:prefix_ +#[no_mangle] +pub extern "C" fn test_prefix(foo_bar: i32) {}