Skip to content

Commit a3ea659

Browse files
committed
Add support for 'unsafe fields'
1 parent 6424e9f commit a3ea659

File tree

6 files changed

+272
-10
lines changed

6 files changed

+272
-10
lines changed

src/gen.rs

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use syntax::print::pprust::tts_to_string;
1919

2020
use super::BindgenOptions;
2121
use super::LinkType;
22+
use parser::Accessor;
2223
use types::*;
2324
use aster;
2425

@@ -840,6 +841,52 @@ fn comp_attrs(ctx: &GenCtx, ci: &CompInfo, name: &str, extra: &mut Vec<P<ast::It
840841
attrs
841842
}
842843

844+
fn gen_accessors(ctx: &mut GenCtx, name: &str, ty: &ast::Ty, accessor: Accessor,
845+
methods: &mut Vec<ast::ImplItem>) {
846+
if accessor == Accessor::None {
847+
return;
848+
}
849+
let ident = ctx.ext_cx.ident_of(&format!("{}", name));
850+
let mutable_getter_name = ctx.ext_cx.ident_of(&format!("get_{}_mut", name));
851+
let getter_name = ctx.ext_cx.ident_of(&format!("get_{}", name));
852+
let imp = match accessor {
853+
Accessor::Regular => quote_item!(&ctx.ext_cx,
854+
impl X {
855+
#[inline]
856+
pub fn $getter_name(&self) -> & $ty {
857+
& self.$ident
858+
}
859+
pub fn $mutable_getter_name(&mut self) -> &mut $ty {
860+
&mut self.$ident
861+
}
862+
}
863+
),
864+
Accessor::Unsafe => quote_item!(&ctx.ext_cx,
865+
impl X {
866+
#[inline]
867+
pub unsafe fn $getter_name(&self) -> & $ty {
868+
& self.$ident
869+
}
870+
pub unsafe fn $mutable_getter_name(&mut self) -> &mut $ty {
871+
&mut self.$ident
872+
}
873+
}
874+
),
875+
Accessor::Immutable => quote_item!(&ctx.ext_cx,
876+
impl X {
877+
#[inline]
878+
pub fn $getter_name(&self) -> & $ty {
879+
& self.$ident
880+
}
881+
}
882+
),
883+
_ => return
884+
};
885+
match imp.unwrap().node {
886+
ast::ItemKind::Impl(_, _, _, _, _, ref items) => methods.extend(items.clone()),
887+
_ => unreachable!()
888+
}
889+
}
843890

844891
fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>> {
845892
let layout = ci.layout;
@@ -878,14 +925,15 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
878925
};
879926

880927
if let Some(ref base) = base_vftable {
881-
vffields.push(ast::StructField {
928+
let field = ast::StructField {
882929
span: ctx.span,
883930
vis: ast::Visibility::Public,
884931
ident: Some(ctx.ext_cx.ident_of("_base")),
885932
id: ast::DUMMY_NODE_ID,
886933
ty: P(mk_ty(ctx, false, &[base.clone()])),
887934
attrs: vec![],
888-
});
935+
};
936+
vffields.push(field);
889937
}
890938

891939
for vm in ci.vmethods.iter() {
@@ -1052,15 +1100,22 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
10521100
} else {
10531101
rust_ty
10541102
};
1055-
1056-
fields.push(ast::StructField {
1103+
let vis = if f.private {
1104+
ast::Visibility::Inherited
1105+
} else {
1106+
ast::Visibility::Public
1107+
};
1108+
gen_accessors(ctx, &f_name, &rust_ty, f.accessor, &mut methods);
1109+
let field = ast::StructField {
10571110
span: ctx.span,
10581111
ident: Some(ctx.ext_cx.ident_of(&f_name)),
1059-
vis: ast::Visibility::Public,
1112+
vis: vis,
10601113
id: ast::DUMMY_NODE_ID,
10611114
ty: rust_ty,
10621115
attrs: mk_doc_attr(ctx, &f.comment)
1063-
});
1116+
};
1117+
fields.push(field);
1118+
10641119
if bypass {
10651120
continue;
10661121
}

src/parser.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
122122
CXCursor_ClassTemplate |
123123
CXCursor_ClassDecl |
124124
CXCursor_StructDecl => {
125+
let anno = Annotations::new(&cursor);
125126
let kind = if cursor.kind() == CXCursor_UnionDecl {
126127
CompKind::Union
127128
} else {
@@ -159,7 +160,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
159160
}
160161
};
161162

162-
let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout);
163+
let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout, anno);
163164
ci.parser_cursor = Some(cursor);
164165

165166
// If it's an instantiation of another template,
@@ -538,12 +539,34 @@ fn opaque_ty(ctx: &mut ClangParserCtx, ty: &cx::Type) {
538539
}
539540
}
540541

541-
struct Annotations {
542+
#[derive(Copy, PartialEq, Clone, Debug)]
543+
pub enum Accessor {
544+
None,
545+
Regular,
546+
Unsafe,
547+
Immutable,
548+
}
549+
550+
#[derive(Clone, PartialEq, Debug)]
551+
pub struct Annotations {
542552
opaque: bool,
543553
hide: bool,
544554
use_as: Option<String>,
545555
/// Disable deriving copy/clone on this struct.
546556
no_copy: bool,
557+
// In the None case we fall back to the value specified
558+
// in the enclosing decl
559+
private: Option<bool>,
560+
accessor: Option<Accessor>,
561+
}
562+
563+
fn parse_accessor(s: &str) -> Accessor {
564+
match s {
565+
"false" => Accessor::None,
566+
"unsafe" => Accessor::Unsafe,
567+
"immutable" => Accessor::Immutable,
568+
_ => Accessor::Regular,
569+
}
547570
}
548571

549572
impl Annotations {
@@ -553,6 +576,8 @@ impl Annotations {
553576
hide: false,
554577
use_as: None,
555578
no_copy: false,
579+
private: None,
580+
accessor: None
556581
};
557582

558583
anno.parse(&cursor.comment());
@@ -571,6 +596,10 @@ impl Annotations {
571596
"hide" => self.hide = true,
572597
"replaces" => self.use_as = Some(comment.get_tag_attr_value(i)),
573598
"nocopy" => self.no_copy = true,
599+
"private" => self.private = Some(comment.get_tag_attr_value(i) != "false"),
600+
"accessor" => {
601+
self.accessor = Some(parse_accessor(&comment.get_tag_attr_value(i)))
602+
},
574603
_ => (),
575604
}
576605
}
@@ -792,12 +821,16 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
792821

793822
if should_replace {
794823
*info = FieldInfo::new(name, ty, comment, bitfields, mutable);
824+
info.private = anno.private.unwrap_or(ci.anno.private.unwrap_or(false));
825+
info.accessor = anno.accessor.unwrap_or(ci.anno.accessor.unwrap_or(Accessor::None));
795826
return CXChildVisit_Continue;
796827
}
797828
}
798829
}
799830

800-
let field = FieldInfo::new(name, ty, comment, bitfields, mutable);
831+
let mut field = FieldInfo::new(name, ty, comment, bitfields, mutable);
832+
field.private = anno.private.unwrap_or(ci.anno.private.unwrap_or(false));
833+
field.accessor = anno.accessor.unwrap_or(ci.anno.accessor.unwrap_or(Accessor::None));
801834
ci.members.push(CompMember::Field(field));
802835
}
803836
CXCursor_StructDecl |

src/types.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub use self::IKind::*;
1313
pub use self::FKind::*;
1414
use clang::Cursor;
1515

16+
use parser::{Annotations, Accessor};
17+
1618
static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
1719

1820
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
@@ -446,6 +448,9 @@ pub struct CompInfo {
446448
/// Used to detect if we've run in a has_destructor cycle while cycling
447449
/// around the template arguments.
448450
detect_has_destructor_cycle: Cell<bool>,
451+
452+
/// Annotations on the decl
453+
pub anno: Annotations,
449454
}
450455

451456
static mut UNNAMED_COUNTER: u32 = 0;
@@ -466,7 +471,8 @@ impl CompInfo {
466471
comment: String,
467472
kind: CompKind,
468473
members: Vec<CompMember>,
469-
layout: Layout) -> CompInfo {
474+
layout: Layout,
475+
anno: Annotations) -> CompInfo {
470476
let was_unnamed = name.is_empty();
471477
CompInfo {
472478
kind: kind,
@@ -494,6 +500,7 @@ impl CompInfo {
494500
was_unnamed: was_unnamed,
495501
detect_derive_debug_cycle: Cell::new(false),
496502
detect_has_destructor_cycle: Cell::new(false),
503+
anno: anno,
497504
}
498505
}
499506

@@ -640,6 +647,8 @@ pub struct FieldInfo {
640647
pub bitfields: Option<Vec<(String, u32)>>,
641648
/// If the C++ field is marked as `mutable`
642649
pub mutable: bool,
650+
pub private: bool,
651+
pub accessor: Accessor,
643652
}
644653

645654
impl FieldInfo {
@@ -654,6 +663,8 @@ impl FieldInfo {
654663
comment: comment,
655664
bitfields: bitfields,
656665
mutable: mutable,
666+
private: false,
667+
accessor: Accessor::None,
657668
}
658669
}
659670
}

tests/expectations/accessors.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Copy)]
9+
pub struct Struct_SomeAccessors {
10+
pub mNoAccessor: ::std::os::raw::c_int,
11+
/** <div rustbindgen accessor></div> */
12+
pub mBothAccessors: ::std::os::raw::c_int,
13+
/** <div rustbindgen accessor="unsafe"></div> */
14+
pub mUnsafeAccessors: ::std::os::raw::c_int,
15+
/** <div rustbindgen accessor="immutable"></div> */
16+
pub mImmutableAccessor: ::std::os::raw::c_int,
17+
}
18+
impl Struct_SomeAccessors {
19+
#[inline]
20+
pub fn get_mBothAccessors(&self) -> &::std::os::raw::c_int {
21+
&self.mBothAccessors
22+
}
23+
pub fn get_mBothAccessors_mut(&mut self) -> &mut ::std::os::raw::c_int {
24+
&mut self.mBothAccessors
25+
}
26+
#[inline]
27+
pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int {
28+
&self.mUnsafeAccessors
29+
}
30+
pub unsafe fn get_mUnsafeAccessors_mut(&mut self)
31+
-> &mut ::std::os::raw::c_int {
32+
&mut self.mUnsafeAccessors
33+
}
34+
#[inline]
35+
pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int {
36+
&self.mImmutableAccessor
37+
}
38+
}
39+
impl ::std::clone::Clone for Struct_SomeAccessors {
40+
fn clone(&self) -> Self { *self }
41+
}
42+
#[test]
43+
fn bindgen_test_layout_Struct_SomeAccessors() {
44+
assert_eq!(::std::mem::size_of::<Struct_SomeAccessors>() , 16usize);
45+
assert_eq!(::std::mem::align_of::<Struct_SomeAccessors>() , 4usize);
46+
}
47+
/** <div rustbindgen accessors></div> */
48+
#[repr(C)]
49+
#[derive(Debug, Copy)]
50+
pub struct Struct_AllAccessors {
51+
pub mBothAccessors: ::std::os::raw::c_int,
52+
pub mAlsoBothAccessors: ::std::os::raw::c_int,
53+
}
54+
impl ::std::clone::Clone for Struct_AllAccessors {
55+
fn clone(&self) -> Self { *self }
56+
}
57+
#[test]
58+
fn bindgen_test_layout_Struct_AllAccessors() {
59+
assert_eq!(::std::mem::size_of::<Struct_AllAccessors>() , 8usize);
60+
assert_eq!(::std::mem::align_of::<Struct_AllAccessors>() , 4usize);
61+
}
62+
/** <div rustbindgen accessors="unsafe"></div> */
63+
#[repr(C)]
64+
#[derive(Debug, Copy)]
65+
pub struct Struct_AllUnsafeAccessors {
66+
pub mBothAccessors: ::std::os::raw::c_int,
67+
pub mAlsoBothAccessors: ::std::os::raw::c_int,
68+
}
69+
impl ::std::clone::Clone for Struct_AllUnsafeAccessors {
70+
fn clone(&self) -> Self { *self }
71+
}
72+
#[test]
73+
fn bindgen_test_layout_Struct_AllUnsafeAccessors() {
74+
assert_eq!(::std::mem::size_of::<Struct_AllUnsafeAccessors>() , 8usize);
75+
assert_eq!(::std::mem::align_of::<Struct_AllUnsafeAccessors>() , 4usize);
76+
}
77+
/** <div rustbindgen accessors></div> */
78+
#[repr(C)]
79+
#[derive(Debug, Copy)]
80+
pub struct Struct_ContradictAccessors {
81+
pub mBothAccessors: ::std::os::raw::c_int,
82+
/** <div rustbindgen accessors="false"></div> */
83+
pub mNoAccessors: ::std::os::raw::c_int,
84+
/** <div rustbindgen accessor="unsafe"></div> */
85+
pub mUnsafeAccessors: ::std::os::raw::c_int,
86+
/** <div rustbindgen accessor="immutable"></div> */
87+
pub mImmutableAccessor: ::std::os::raw::c_int,
88+
}
89+
impl Struct_ContradictAccessors {
90+
#[inline]
91+
pub unsafe fn get_mUnsafeAccessors(&self) -> &::std::os::raw::c_int {
92+
&self.mUnsafeAccessors
93+
}
94+
pub unsafe fn get_mUnsafeAccessors_mut(&mut self)
95+
-> &mut ::std::os::raw::c_int {
96+
&mut self.mUnsafeAccessors
97+
}
98+
#[inline]
99+
pub fn get_mImmutableAccessor(&self) -> &::std::os::raw::c_int {
100+
&self.mImmutableAccessor
101+
}
102+
}
103+
impl ::std::clone::Clone for Struct_ContradictAccessors {
104+
fn clone(&self) -> Self { *self }
105+
}
106+
#[test]
107+
fn bindgen_test_layout_Struct_ContradictAccessors() {
108+
assert_eq!(::std::mem::size_of::<Struct_ContradictAccessors>() , 16usize);
109+
assert_eq!(::std::mem::align_of::<Struct_ContradictAccessors>() , 4usize);
110+
}

tests/headers/accessors.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
struct SomeAccessors {
2+
int mNoAccessor;
3+
/** <div rustbindgen accessor></div> */
4+
int mBothAccessors;
5+
/** <div rustbindgen accessor="unsafe"></div> */
6+
int mUnsafeAccessors;
7+
/** <div rustbindgen accessor="immutable"></div> */
8+
int mImmutableAccessor;
9+
};
10+
11+
/** <div rustbindgen accessors></div> */
12+
struct AllAccessors {
13+
int mBothAccessors;
14+
int mAlsoBothAccessors;
15+
};
16+
17+
/** <div rustbindgen accessors="unsafe"></div> */
18+
struct AllUnsafeAccessors {
19+
int mBothAccessors;
20+
int mAlsoBothAccessors;
21+
};
22+
23+
/** <div rustbindgen accessors></div> */
24+
struct ContradictAccessors {
25+
int mBothAccessors;
26+
/** <div rustbindgen accessors="false"></div> */
27+
int mNoAccessors;
28+
/** <div rustbindgen accessor="unsafe"></div> */
29+
int mUnsafeAccessors;
30+
/** <div rustbindgen accessor="immutable"></div> */
31+
int mImmutableAccessor;
32+
};

0 commit comments

Comments
 (0)