Skip to content

Commit

Permalink
Add callback to override field visibility
Browse files Browse the repository at this point in the history
  • Loading branch information
Jethro Beekman committed May 17, 2023
1 parent 6ad94ba commit 182699e
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 18 deletions.
185 changes: 185 additions & 0 deletions bindgen-tests/tests/expectations/tests/field-visibility-callback.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions bindgen-tests/tests/headers/field-visibility-callback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// bindgen-flags: --default-visibility private
// bindgen-parse-callbacks: field-visibility

struct my_struct {
int a;
int private_b;
int c: 1;
int private_d: 1;
};
18 changes: 18 additions & 0 deletions bindgen-tests/tests/parse_callbacks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,27 @@ impl ParseCallbacks for BlocklistedTypeImplementsTrait {
}
}

#[derive(Debug)]
struct FieldVisibility;

impl ParseCallbacks for FieldVisibility {
fn field_visibility(
&self,
_type_name: &str,
field_name: &str,
) -> Option<bindgen::FieldVisibilityKind> {
if !field_name.starts_with("private_") {
Some(bindgen::FieldVisibilityKind::Public)
} else {
None
}
}
}

pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
match cb {
"enum-variant-rename" => Box::new(EnumVariantRename),
"field-visibility" => Box::new(FieldVisibility),
"blocklisted-type-implements-trait" => {
Box::new(BlocklistedTypeImplementsTrait)
}
Expand Down
9 changes: 9 additions & 0 deletions bindgen/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ pub trait ParseCallbacks: fmt::Debug {
fn process_comment(&self, _comment: &str) -> Option<String> {
None
}

/// Potentially override the visibility of a composite type field
fn field_visibility(
&self,
_type_name: &str,
_field_name: &str,
) -> Option<crate::FieldVisibilityKind> {
None
}
}

/// Relevant information about a type to which new derive attributes will be added using
Expand Down
58 changes: 40 additions & 18 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@ trait FieldCodegen<'a> {
visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
parent_item: &Item,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
Expand All @@ -1310,6 +1311,7 @@ impl<'a> FieldCodegen<'a> for Field {
visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
parent_item: &Item,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
Expand All @@ -1326,6 +1328,7 @@ impl<'a> FieldCodegen<'a> for Field {
visibility_kind,
accessor_kind,
parent,
parent_item,
result,
struct_layout,
fields,
Expand All @@ -1339,6 +1342,7 @@ impl<'a> FieldCodegen<'a> for Field {
visibility_kind,
accessor_kind,
parent,
parent_item,
result,
struct_layout,
fields,
Expand Down Expand Up @@ -1388,6 +1392,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
parent_visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
parent_item: &Item,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
Expand Down Expand Up @@ -1451,6 +1456,12 @@ impl<'a> FieldCodegen<'a> for FieldData {
let visibility = compute_visibility(
ctx,
self.is_public(),
ctx.options().last_callback(|cb| {
cb.field_visibility(
&parent_item.canonical_name(ctx),
&field_name,
)
}),
self.annotations(),
parent_visibility_kind,
);
Expand Down Expand Up @@ -1604,27 +1615,28 @@ fn access_specifier(
fn compute_visibility(
ctx: &BindgenContext,
is_declared_public: bool,
callback_override: Option<FieldVisibilityKind>,
annotations: &Annotations,
default_kind: FieldVisibilityKind,
) -> FieldVisibilityKind {
match (
is_declared_public,
ctx.options().respect_cxx_access_specs,
annotations.visibility_kind(),
) {
(true, true, annotated_visibility) => {
// declared as public, cxx specs are respected
annotated_visibility.unwrap_or(FieldVisibilityKind::Public)
}
(false, true, annotated_visibility) => {
// declared as private, cxx specs are respected
annotated_visibility.unwrap_or(FieldVisibilityKind::Private)
}
(_, false, annotated_visibility) => {
// cxx specs are not respected, declaration does not matter.
annotated_visibility.unwrap_or(default_kind)
}
}
callback_override
.or_else(|| annotations.visibility_kind())
.unwrap_or_else(|| {
match (is_declared_public, ctx.options().respect_cxx_access_specs) {
(true, true) => {
// declared as public, cxx specs are respected
FieldVisibilityKind::Public
}
(false, true) => {
// declared as private, cxx specs are respected
FieldVisibilityKind::Private
}
(_, false) => {
// cxx specs are not respected, declaration does not matter.
default_kind
}
}
})
}

impl<'a> FieldCodegen<'a> for BitfieldUnit {
Expand All @@ -1636,6 +1648,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
visibility_kind: FieldVisibilityKind,
accessor_kind: FieldAccessorKind,
parent: &CompInfo,
parent_item: &Item,
result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
Expand Down Expand Up @@ -1715,6 +1728,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
visibility_kind,
accessor_kind,
parent,
parent_item,
result,
struct_layout,
fields,
Expand Down Expand Up @@ -1796,6 +1810,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
visibility_kind: FieldVisibilityKind,
_accessor_kind: FieldAccessorKind,
parent: &CompInfo,
parent_item: &Item,
_result: &mut CodegenResult,
struct_layout: &mut StructLayoutTracker,
_fields: &mut F,
Expand Down Expand Up @@ -1838,9 +1853,15 @@ impl<'a> FieldCodegen<'a> for Bitfield {
let offset = self.offset_into_unit();
let width = self.width() as u8;

let override_visibility = self.name().and_then(|fname| {
ctx.options().last_callback(|cb| {
cb.field_visibility(&parent_item.canonical_name(ctx), fname)
})
});
*bitfield_visibility = compute_visibility(
ctx,
self.is_public(),
override_visibility,
self.annotations(),
visibility_kind,
);
Expand Down Expand Up @@ -2007,6 +2028,7 @@ impl CodeGenerator for CompInfo {
visibility,
struct_accessor_kind,
self,
item,
result,
&mut struct_layout,
&mut fields,
Expand Down

0 comments on commit 182699e

Please sign in to comment.