Skip to content

Commit

Permalink
Add rename rule for generated associated constant's base name
Browse files Browse the repository at this point in the history
In FFI Rust code it is often necessary to use constants instead of enums
for compatibility reasons. The most natural thing to do to somewhat
preserve grouping is to use associated constants. E.g.:

  ```rust
  #[repr(C)]
  struct Foo {}

  impl Foo {
      pub const FLAG1: u32 = 10;
      pub const FLAG2: u32 = 11;
      ...
  ```

For the above, the generated constants would be called Foo_FLAG1 &
Foo_FLAG2. Many Linux core C libraries adhere to a slightly different
casing, however, where the type prefix is fully upper cased: FOO_FLAG1.
Currently, it does not seem possible to generate such constants.

This change introduces a new config option to structured types that
enables this use case: the struct.associated_constants_rename_base_name
option expects a rename rule (as other rename related config options)
and applies it to the struct base name as used in conjunction with
associated constants to form the final name of the constant.

Signed-off-by: Daniel Müller <[email protected]>
  • Loading branch information
d-e-s-o committed Dec 12, 2024
1 parent b9b8f88 commit 8bdb216
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
/// The way to annotation this function as #[deprecated] without notes
Expand Down
17 changes: 16 additions & 1 deletion src/bindgen/ir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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::<RenameRule>("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);
Expand Down
1 change: 1 addition & 0 deletions template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions tests/expectations/associated_constants_rename_base_name.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {

} Foo;
#define FOO_GA 10
#define FOO_ZO 3.14

void root(Foo x);
20 changes: 20 additions & 0 deletions tests/expectations/associated_constants_rename_base_name.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

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
17 changes: 17 additions & 0 deletions tests/expectations/associated_constants_rename_base_name.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

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"
14 changes: 14 additions & 0 deletions tests/expectations/associated_constants_rename_base_name.pyx
Original file line number Diff line number Diff line change
@@ -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);
12 changes: 12 additions & 0 deletions tests/expectations/associated_constants_rename_base_name_both.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct Foo {

} Foo;
#define FOO_GA 10
#define FOO_ZO 3.14

void root(struct Foo x);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

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
12 changes: 12 additions & 0 deletions tests/expectations/associated_constants_rename_base_name_tag.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

struct Foo {

};
#define FOO_GA 10
#define FOO_ZO 3.14

void root(struct Foo x);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

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
14 changes: 14 additions & 0 deletions tests/expectations/associated_constants_rename_base_name_tag.pyx
Original file line number Diff line number Diff line change
@@ -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);
11 changes: 11 additions & 0 deletions tests/rust/associated_constants_rename_base_name.rs
Original file line number Diff line number Diff line change
@@ -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) { }
2 changes: 2 additions & 0 deletions tests/rust/associated_constants_rename_base_name.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[struct]
associated_constants_rename_base_name = "UpperCase"

0 comments on commit 8bdb216

Please sign in to comment.