Skip to content

Commit fb65a21

Browse files
committed
Add support for 'unsafe fields'
1 parent 4f92390 commit fb65a21

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

src/bin/bindgen.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ fn parse_args(args: &[String]) -> ParseResult {
109109
options.opaque_types.push(args[ix + 1].clone());
110110
ix += 2;
111111
}
112+
"-unsafe-field-type" => {
113+
if ix + 1 >= args_len {
114+
return ParseResult::ParseErr("Missing unsafe field type name".to_string());
115+
}
116+
options.unsafe_field_types.push(args[ix + 1].clone());
117+
ix += 2;
118+
}
112119
"-builtins" => {
113120
options.builtins = true;
114121
ix += 1;

src/gen.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,59 @@ fn comp_attrs(ctx: &GenCtx, ci: &CompInfo, name: &str, extra: &mut Vec<P<ast::It
841841
attrs
842842
}
843843

844+
fn gen_maybe_unsafe_field(ctx: &mut GenCtx, mut field: ast::StructField, methods: &mut Vec<ast::ImplItem>) -> ast::StructField {
845+
use syntax::visit::{Visitor, walk_ty};
846+
struct TyVisitor<'a> {
847+
search: &'a [String],
848+
found: bool
849+
};
850+
impl<'a> Visitor for TyVisitor<'a> {
851+
fn visit_ty(&mut self, t: &ast::Ty) {
852+
if let ast::TyKind::Path(_, ref p) = t.node {
853+
if p.segments.len() == 1 {
854+
for name in self.search {
855+
if p.segments[0].identifier.name.as_str() == **name {
856+
self.found = true;
857+
return;
858+
}
859+
}
860+
}
861+
}
862+
walk_ty(self, t)
863+
}
864+
}
865+
866+
if !ctx.options.unsafe_field_types.is_empty() {
867+
let mut visit = TyVisitor {search: &ctx.options.unsafe_field_types, found: false};
868+
walk_ty(&mut visit, &field.ty);
869+
if visit.found {
870+
field.vis = ast::Visibility::Inherited;
871+
let ident = field.ident.unwrap();
872+
let mutable_getter_name = ctx.ext_cx.ident_of(&format!("get_{}_mut", ident));
873+
let getter_name = ctx.ext_cx.ident_of(&format!("get_{}", ident));
874+
{
875+
let ref ty = field.ty;
876+
let imp = quote_item!(&ctx.ext_cx,
877+
impl X {
878+
#[inline]
879+
pub unsafe fn $getter_name(&self) -> & $ty {
880+
& self.$ident
881+
}
882+
pub unsafe fn $mutable_getter_name(&mut self) -> &mut $ty {
883+
&mut self.$ident
884+
}
885+
}
886+
);
887+
match imp.unwrap().node {
888+
ast::ItemKind::Impl(_, _, _, _, _, ref items) => methods.extend(items.clone()),
889+
_ => unreachable!()
890+
}
891+
}
892+
return field;
893+
}
894+
}
895+
field
896+
}
844897

845898
fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>> {
846899
let layout = ci.layout;
@@ -879,14 +932,15 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
879932
};
880933

881934
if let Some(ref base) = base_vftable {
882-
vffields.push(ast::StructField {
935+
let field = ast::StructField {
883936
span: ctx.span,
884937
vis: ast::Visibility::Public,
885938
ident: Some(ctx.ext_cx.ident_of("_base")),
886939
id: ast::DUMMY_NODE_ID,
887940
ty: P(mk_ty(ctx, false, &[base.clone()])),
888941
attrs: vec![],
889-
});
942+
};
943+
vffields.push(gen_maybe_unsafe_field(ctx, field, &mut methods));
890944
}
891945

892946
for vm in ci.vmethods.iter() {
@@ -1053,15 +1107,15 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
10531107
} else {
10541108
rust_ty
10551109
};
1056-
1057-
fields.push(ast::StructField {
1110+
let field = ast::StructField {
10581111
span: ctx.span,
10591112
ident: Some(ctx.ext_cx.ident_of(&f_name)),
10601113
vis: ast::Visibility::Public,
10611114
id: ast::DUMMY_NODE_ID,
10621115
ty: rust_ty,
10631116
attrs: mk_doc_attr(ctx, &f.comment)
1064-
});
1117+
};
1118+
fields.push(gen_maybe_unsafe_field(ctx, field, &mut methods));
10651119
if bypass {
10661120
continue;
10671121
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ pub struct BindgenOptions {
154154
pub match_pat: Vec<String>,
155155
pub blacklist_type: Vec<String>,
156156
pub opaque_types: Vec<String>,
157+
pub unsafe_field_types: Vec<String>,
157158
pub builtins: bool,
158159
pub rust_enums: bool,
159160
pub links: Vec<(String, LinkType)>,
@@ -185,6 +186,7 @@ impl Default for BindgenOptions {
185186
match_pat: vec![],
186187
blacklist_type: vec![],
187188
opaque_types: vec![],
189+
unsafe_field_types: vec![],
188190
builtins: false,
189191
rust_enums: true,
190192
links: vec![],

0 commit comments

Comments
 (0)