Skip to content

Commit 430055d

Browse files
committed
Add ParseCallbacks::allow_item() and ParseCallbacks::block_item().
Like `allowlist_item` and `blocklist_item` options, add new methods to `ParseCallbacks`, `ParseCallbacks::allow_item()` and `ParseCallbacks::block_item()`, to be able to allow and block items from being generated. `allowlist_*` and `blocklist_*` options work with regexes and are inserted in a RegexSet. There are two issues with this approach: 1. In some cases we want to have more flexibility than just using regexes. If we want to have dynamic conditions to allow or block items, using regexes can be limited. 2. RegexSet scales linearly with the number of elements inserted. This means that if we have a huge number of items that we want to allow or block, regexes and RegexSet are not necessarily the most appropriate data structures. Using new methods in `ParseCallbacks` solves these two issues. We can manually decide the appropriate rules and data structure to match the items. `ParseCallbacks::allow_item()` and `ParseCallbacks::block_item()` are always called after the `allowlist_*` and `blocklist_*` options, and allow or do not block the items by default respectively.
1 parent 1f02556 commit 430055d

File tree

10 files changed

+262
-12
lines changed

10 files changed

+262
-12
lines changed

bindgen-tests/tests/expectations/tests/allow-item-callback.rs

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/block-item-callback.rs

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// bindgen-parse-callbacks: allow-item
2+
3+
struct allowed_my_struct {
4+
int a;
5+
};
6+
7+
union allowed_my_union {
8+
int a;
9+
double b;
10+
};
11+
12+
enum allowed_my_enum {
13+
ALLOWED_MY_ENUM_A,
14+
ALLOWED_MY_ENUM_B,
15+
};
16+
17+
static const int allowed_my_const = 10;
18+
19+
struct non_allowed_my_struct {
20+
int a;
21+
};
22+
23+
union non_allowed_my_union {
24+
int a;
25+
double b;
26+
};
27+
28+
enum non_allowed_my_enum {
29+
NON_ALLOWED_MY_ENUM_A,
30+
NON_ALLOWED_MY_ENUM_B,
31+
};
32+
33+
static const int non_allowed_my_const = 10;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// bindgen-parse-callbacks: block-item
2+
3+
struct blocked_my_struct {
4+
int a;
5+
};
6+
7+
union blocked_my_union {
8+
int a;
9+
double b;
10+
};
11+
12+
enum blocked_my_enum {
13+
BLOCKED_MY_ENUM_A,
14+
BLOCKED_MY_ENUM_B,
15+
};
16+
17+
static const int blocked_my_const = 10;
18+
19+
struct non_blocked_my_struct {
20+
int a;
21+
};
22+
23+
union non_blocked_my_union {
24+
int a;
25+
double b;
26+
};
27+
28+
enum non_blocked_my_enum {
29+
NON_BLOCKED_MY_ENUM_A,
30+
NON_BLOCKED_MY_ENUM_B,
31+
};
32+
33+
static const int non_blocked_my_const = 10;

bindgen-tests/tests/parse_callbacks/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ impl ParseCallbacks for OperatorRename {
159159
}
160160
}
161161

162+
#[derive(Debug)]
163+
struct AllowItem;
164+
165+
impl ParseCallbacks for AllowItem {
166+
fn allow_item(&self, item: ItemInfo) -> bool {
167+
item.name.starts_with("allowed_")
168+
}
169+
}
170+
171+
#[derive(Debug)]
172+
struct BlockItem;
173+
174+
impl ParseCallbacks for BlockItem {
175+
fn block_item(&self, item: ItemInfo) -> bool {
176+
item.name.starts_with("blocked_")
177+
}
178+
}
179+
162180
pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
163181
match cb {
164182
"enum-variant-rename" => Box::new(EnumVariantRename),
@@ -168,6 +186,8 @@ pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
168186
"wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn),
169187
"type-visibility" => Box::new(TypeVisibility),
170188
"operator-rename" => Box::new(OperatorRename),
189+
"allow-item" => Box::new(AllowItem),
190+
"block-item" => Box::new(BlockItem),
171191
call_back => {
172192
if let Some(prefix) =
173193
call_back.strip_prefix("remove-function-prefix-")

bindgen/callbacks.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,24 @@ pub trait ParseCallbacks: fmt::Debug {
171171
/// This will get called everytime an item (currently struct, union, and alias) is found with some information about it
172172
fn new_item_found(&self, _id: DiscoveredItemId, _item: DiscoveredItem) {}
173173

174+
/// Generate bindings for the given item.
175+
///
176+
/// This method is called after processing the `allowlist_*` options.
177+
///
178+
/// The default implementation is to allow the given item.
179+
fn allow_item(&self, _item: ItemInfo) -> bool {
180+
true
181+
}
182+
183+
/// Block bindings for the given item.
184+
///
185+
/// This method is called after processing the `blocklist_*` options.
186+
///
187+
/// The default implementation is to not block the given item.
188+
fn block_item(&self, _item: ItemInfo) -> bool {
189+
false
190+
}
191+
174192
// TODO add callback for ResolvedTypeRef
175193
}
176194

bindgen/codegen/mod.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use super::BindgenOptions;
2222

2323
use crate::callbacks::{
2424
AttributeInfo, DeriveInfo, DiscoveredItem, DiscoveredItemId, FieldInfo,
25-
TypeKind as DeriveTypeKind,
25+
ItemInfo, ItemKind as CallbackItemKind, TypeKind as DeriveTypeKind,
2626
};
2727
use crate::codegen::error::Error;
2828
use crate::ir::analysis::{HasVtable, Sizedness};
@@ -4942,7 +4942,14 @@ fn objc_method_codegen(
49424942
// Item::process_before_codegen; however, ObjC methods are not currently
49434943
// made into function items.
49444944
let name = format!("{rust_class_name}::{prefix}{}", method.rust_name());
4945-
if ctx.options().blocklisted_items.matches(name) {
4945+
let item_info = ItemInfo {
4946+
name: &name,
4947+
kind: CallbackItemKind::Function,
4948+
};
4949+
if ctx.options().blocklisted_items.matches(&name) ||
4950+
ctx.options()
4951+
.for_any_callback(|cb| cb.block_item(item_info))
4952+
{
49464953
return;
49474954
}
49484955

@@ -5259,6 +5266,7 @@ pub(crate) mod utils {
52595266
use super::helpers::BITFIELD_UNIT;
52605267
use super::serialize::CSerialize;
52615268
use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
5269+
use crate::callbacks::{ItemInfo, ItemKind as CallbackItemKind};
52625270
use crate::ir::context::BindgenContext;
52635271
use crate::ir::context::TypeId;
52645272
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
@@ -5389,8 +5397,14 @@ pub(crate) mod utils {
53895397
ctx: &BindgenContext,
53905398
result: &mut Vec<proc_macro2::TokenStream>,
53915399
) {
5400+
let item_info = ItemInfo {
5401+
name: BITFIELD_UNIT,
5402+
kind: CallbackItemKind::Type,
5403+
};
53925404
if ctx.options().blocklisted_items.matches(BITFIELD_UNIT) ||
5393-
ctx.options().blocklisted_types.matches(BITFIELD_UNIT)
5405+
ctx.options().blocklisted_types.matches(BITFIELD_UNIT) ||
5406+
ctx.options()
5407+
.for_any_callback(|cb| cb.block_item(item_info))
53945408
{
53955409
return;
53965410
}

bindgen/ir/context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use super::traversal::{self, Edge, ItemTraversal};
2121
use super::ty::{FloatKind, Type, TypeKind};
2222
use crate::clang::{self, ABIKind, Cursor};
2323
use crate::codegen::CodegenError;
24+
use crate::ir::item::ItemCanonicalName;
2425
use crate::BindgenOptions;
2526
use crate::{Entry, HashMap, HashSet};
2627

@@ -2519,6 +2520,14 @@ If you encounter an error missing from this list, please file an issue or a PR!"
25192520
}
25202521
}
25212522
})
2523+
.filter(|&(_, item)| {
2524+
let item_info = crate::callbacks::ItemInfo {
2525+
name: &item.canonical_name(self),
2526+
kind: item.callback_item_kind(),
2527+
};
2528+
self.options()
2529+
.for_all_callbacks(|cb| cb.allow_item(item_info))
2530+
})
25222531
.map(|(id, _)| id)
25232532
.collect::<Vec<_>>();
25242533

bindgen/ir/item.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,10 @@ impl Item {
653653

654654
let path = self.path_for_allowlisting(ctx);
655655
let name = path[1..].join("::");
656+
let item_info = ItemInfo {
657+
name: &name,
658+
kind: self.callback_item_kind(),
659+
};
656660
ctx.options().blocklisted_items.matches(&name) ||
657661
match self.kind {
658662
ItemKind::Type(..) => {
@@ -667,7 +671,9 @@ impl Item {
667671
}
668672
// TODO: Add namespace blocklisting?
669673
ItemKind::Module(..) => false,
670-
}
674+
} ||
675+
ctx.options()
676+
.for_any_callback(|cb| cb.block_item(item_info))
671677
}
672678

673679
/// Take out item `NameOptions`
@@ -818,6 +824,16 @@ impl Item {
818824
}
819825
}
820826

827+
// Get the callback item kind of this item.
828+
pub(crate) fn callback_item_kind(&self) -> crate::callbacks::ItemKind {
829+
match self.kind() {
830+
ItemKind::Module(..) => crate::callbacks::ItemKind::Module,
831+
ItemKind::Type(..) => crate::callbacks::ItemKind::Type,
832+
ItemKind::Function(..) => crate::callbacks::ItemKind::Function,
833+
ItemKind::Var(..) => crate::callbacks::ItemKind::Var,
834+
}
835+
}
836+
821837
/// Get the canonical name without taking into account the replaces
822838
/// annotation.
823839
///
@@ -925,14 +941,7 @@ impl Item {
925941
let name = if opt.user_mangled == UserMangled::Yes {
926942
let item_info = ItemInfo {
927943
name: &name,
928-
kind: match self.kind() {
929-
ItemKind::Module(..) => crate::callbacks::ItemKind::Module,
930-
ItemKind::Type(..) => crate::callbacks::ItemKind::Type,
931-
ItemKind::Function(..) => {
932-
crate::callbacks::ItemKind::Function
933-
}
934-
ItemKind::Var(..) => crate::callbacks::ItemKind::Var,
935-
},
944+
kind: self.callback_item_kind(),
936945
};
937946
ctx.options()
938947
.last_callback(|callbacks| callbacks.item_name(item_info))

bindgen/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,20 @@ impl BindgenOptions {
591591
self.parse_callbacks.iter().for_each(|cb| f(cb.as_ref()));
592592
}
593593

594+
fn for_all_callbacks(
595+
&self,
596+
f: impl Fn(&dyn callbacks::ParseCallbacks) -> bool,
597+
) -> bool {
598+
self.parse_callbacks.iter().all(|cb| f(cb.as_ref()))
599+
}
600+
601+
fn for_any_callback(
602+
&self,
603+
f: impl Fn(&dyn callbacks::ParseCallbacks) -> bool,
604+
) -> bool {
605+
self.parse_callbacks.iter().any(|cb| f(cb.as_ref()))
606+
}
607+
594608
fn process_comment(&self, comment: &str) -> String {
595609
let comment = comment::preprocess(comment);
596610
self.last_callback(|cb| cb.process_comment(&comment))

0 commit comments

Comments
 (0)