diff --git a/docs.md b/docs.md index c8ce9f4f..ff7cf171 100644 --- a/docs.md +++ b/docs.md @@ -828,6 +828,12 @@ deprecated_with_notes = "DEPRECATED_STRUCT_WITH_NOTE" # default: false # associated_constants_in_body: false +# The rename rule to apply to the struct name used for prefixing associated +# constants. +# +# default: "None" +associated_constants_rename_base_name: "None" + # Whether to derive a simple constructor that takes a value for every field. # default: false derive_constructor = true diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index 31316503..23813dea 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -493,6 +493,9 @@ pub struct StructConfig { /// Whether associated constants should be in the body. Only applicable to /// non-transparent structs, and in C++-only. pub associated_constants_in_body: bool, + /// The rename rule to apply to the struct name used for prefixing associated + /// constants + pub associated_constants_rename_base_name: RenameRule, /// The way to annotate this struct as #[must_use]. pub must_use: Option, /// The way to annotation this function as #[deprecated] without notes diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index ca6499d8..938b2d8f 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -18,6 +18,7 @@ use crate::bindgen::ir::{ }; use crate::bindgen::language_backend::LanguageBackend; use crate::bindgen::library::Library; +use crate::bindgen::rename::{IdentifierType, RenameRule}; use crate::bindgen::writer::SourceWriter; use crate::bindgen::Bindings; @@ -666,7 +667,21 @@ impl Constant { Cow::Borrowed(self.export_name()) } else { let associated_name = match associated_to_struct { - Some(s) => Cow::Borrowed(s.export_name()), + Some(s) => { + let name = s.export_name(); + let rules = s + .annotations + .parse_atom::("associated-constants-rename-base-name"); + let rules = rules + .as_ref() + .unwrap_or(&config.structure.associated_constants_rename_base_name); + + if let Some(r) = rules.not_none() { + r.apply(name, IdentifierType::Type) + } else { + Cow::Borrowed(name) + } + } None => { let mut name = self.associated_to.as_ref().unwrap().name().to_owned(); config.export.rename(&mut name); diff --git a/template.toml b/template.toml index a2f18a68..a46aa997 100644 --- a/template.toml +++ b/template.toml @@ -95,6 +95,7 @@ rename_fields = "None" # must_use = "MUST_USE_STRUCT" # deprecated = "DEPRECATED_STRUCT" # deprecated_with_note = "DEPRECATED_STRUCT_WITH_NOTE" +associated_constants_rename_base_name = "None" derive_constructor = false derive_eq = false derive_neq = false diff --git a/tests/expectations/associated_constants_rename_base_name.c b/tests/expectations/associated_constants_rename_base_name.c new file mode 100644 index 00000000..fce0955b --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +typedef struct { + +} Foo; +#define FOO_GA 10 +#define FOO_ZO 3.14 + +void root(Foo x); diff --git a/tests/expectations/associated_constants_rename_base_name.compat.c b/tests/expectations/associated_constants_rename_base_name.compat.c new file mode 100644 index 00000000..7160635e --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +typedef struct { + +} Foo; +#define FOO_GA 10 +#define FOO_ZO 3.14 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(Foo x); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/associated_constants_rename_base_name.cpp b/tests/expectations/associated_constants_rename_base_name.cpp new file mode 100644 index 00000000..8d8bb9f0 --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name.cpp @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include + +struct Foo { + +}; +constexpr static const int32_t FOO_GA = 10; +constexpr static const float FOO_ZO = 3.14; + +extern "C" { + +void root(Foo x); + +} // extern "C" diff --git a/tests/expectations/associated_constants_rename_base_name.pyx b/tests/expectations/associated_constants_rename_base_name.pyx new file mode 100644 index 00000000..d6560451 --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name.pyx @@ -0,0 +1,14 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + ctypedef struct Foo: + pass + const int32_t FOO_GA # = 10 + const float FOO_ZO # = 3.14 + + void root(Foo x); diff --git a/tests/expectations/associated_constants_rename_base_name_both.c b/tests/expectations/associated_constants_rename_base_name_both.c new file mode 100644 index 00000000..29c4ef9c --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name_both.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +typedef struct Foo { + +} Foo; +#define FOO_GA 10 +#define FOO_ZO 3.14 + +void root(struct Foo x); diff --git a/tests/expectations/associated_constants_rename_base_name_both.compat.c b/tests/expectations/associated_constants_rename_base_name_both.compat.c new file mode 100644 index 00000000..1f3cd1e0 --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name_both.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +typedef struct Foo { + +} Foo; +#define FOO_GA 10 +#define FOO_ZO 3.14 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct Foo x); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/associated_constants_rename_base_name_tag.c b/tests/expectations/associated_constants_rename_base_name_tag.c new file mode 100644 index 00000000..db78b0c6 --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name_tag.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +struct Foo { + +}; +#define FOO_GA 10 +#define FOO_ZO 3.14 + +void root(struct Foo x); diff --git a/tests/expectations/associated_constants_rename_base_name_tag.compat.c b/tests/expectations/associated_constants_rename_base_name_tag.compat.c new file mode 100644 index 00000000..7c8fa2ad --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name_tag.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +struct Foo { + +}; +#define FOO_GA 10 +#define FOO_ZO 3.14 + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct Foo x); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/associated_constants_rename_base_name_tag.pyx b/tests/expectations/associated_constants_rename_base_name_tag.pyx new file mode 100644 index 00000000..6d4c628e --- /dev/null +++ b/tests/expectations/associated_constants_rename_base_name_tag.pyx @@ -0,0 +1,14 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + cdef struct Foo: + pass + const int32_t FOO_GA # = 10 + const float FOO_ZO # = 3.14 + + void root(Foo x); diff --git a/tests/rust/associated_constants_rename_base_name.rs b/tests/rust/associated_constants_rename_base_name.rs new file mode 100644 index 00000000..19a24b13 --- /dev/null +++ b/tests/rust/associated_constants_rename_base_name.rs @@ -0,0 +1,11 @@ +/// cbindgen:associated-constants-rename-base-name=UpperCase +#[repr(C)] +struct Foo {} + +impl Foo { + pub const GA: i32 = 10; + pub const ZO: f32 = 3.14; +} + +#[no_mangle] +pub extern "C" fn root(x: Foo) { } diff --git a/tests/rust/associated_constants_rename_base_name.toml b/tests/rust/associated_constants_rename_base_name.toml new file mode 100644 index 00000000..7bcfea45 --- /dev/null +++ b/tests/rust/associated_constants_rename_base_name.toml @@ -0,0 +1,2 @@ +[struct] +associated_constants_rename_base_name = "UpperCase"