/
annotations.rs
160 lines (145 loc) · 4.89 KB
/
annotations.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! Types and functions related to bindgen annotation comments.
//!
//! Users can add annotations in doc comments to types that they would like to
//! replace other types with, mark as opaque, etc. This module deals with all of
//! that stuff.
use clang;
/// What kind of accessor should we provide for a field?
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum FieldAccessorKind {
/// No accessor.
None,
/// Plain accessor.
Regular,
/// Unsafe accessor.
Unsafe,
/// Immutable accessor.
Immutable,
}
/// Annotations for a given item, or a field.
#[derive(Clone, PartialEq, Debug)]
pub struct Annotations {
/// Whether this item is marked as opaque. Only applies to types.
opaque: bool,
/// Whether this item should be hidden from the output. Only applies to
/// types.
hide: bool,
/// Whether this type should be replaced by another. The name must be the
/// canonical name that that type would get.
use_instead_of: Option<String>,
/// Manually disable deriving copy/clone on this type. Only applies to
/// struct or union types.
disallow_copy: bool,
/// Whether fields should be marked as private or not. You can set this on
/// structs (it will apply to all the fields), or individual fields.
private_fields: Option<bool>,
/// The kind of accessor this field will have. Also can be applied to
/// structs so all the fields inside share it by default.
accessor_kind: Option<FieldAccessorKind>,
}
fn parse_accessor(s: &str) -> FieldAccessorKind {
match s {
"false" => FieldAccessorKind::None,
"unsafe" => FieldAccessorKind::Unsafe,
"immutable" => FieldAccessorKind::Immutable,
_ => FieldAccessorKind::Regular,
}
}
impl Default for Annotations {
fn default() -> Self {
Annotations {
opaque: false,
hide: false,
use_instead_of: None,
disallow_copy: false,
private_fields: None,
accessor_kind: None
}
}
}
impl Annotations {
/// Construct new annotations for the given cursor and its bindgen comments
/// (if any).
pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
let mut anno = Annotations::default();
let mut matched_one = false;
anno.parse(&cursor.comment(), &mut matched_one);
if matched_one {
Some(anno)
} else {
None
}
}
/// Should this type be hidden?
pub fn hide(&self) -> bool {
self.hide
}
/// Should this type be opaque?
pub fn opaque(&self) -> bool {
self.opaque
}
/// For a given type, indicates the type it should replace.
///
/// For example, in the following code:
///
/// ```cpp
///
/// /** <div rustbindgen replaces="Bar"></div> */
/// struct Foo { int x; };
///
/// struct Bar { char foo; };
/// ```
///
/// the generated code would look something like:
///
/// ```
/// /** <div rustbindgen replaces="Bar"></div> */
/// struct Bar {
/// x: ::std::os::raw::c_int,
/// };
/// ```
///
/// That is, code for `Foo` is used to generate `Bar`.
pub fn use_instead_of(&self) -> Option<&str> {
self.use_instead_of.as_ref().map(|s| &**s)
}
/// Should we avoid implementing the `Copy` trait?
pub fn disallow_copy(&self) -> bool {
self.disallow_copy
}
/// Should the fields be private?
pub fn private_fields(&self) -> Option<bool> {
self.private_fields
}
/// What kind of accessors should we provide for this type's fields?
pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
self.accessor_kind
}
fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
use clangll::CXComment_HTMLStartTag;
if comment.kind() == CXComment_HTMLStartTag &&
comment.get_tag_name() == "div" &&
comment.get_num_tag_attrs() > 1 &&
comment.get_tag_attr_name(0).as_ref().map(|s| s.as_str())
== Some("rustbindgen") {
*matched = true;
for i in 0..comment.get_num_tag_attrs() {
let value_opt = comment.get_tag_attr_value(i);
match comment.get_tag_attr_name(i).unwrap().as_str() {
"opaque" => self.opaque = true,
"hide" => self.hide = true,
"nocopy" => self.disallow_copy = true,
"replaces" => self.use_instead_of = value_opt,
"private" => self.private_fields = value_opt.map(|v|
v != "false"),
"accessor" => self.accessor_kind = value_opt.map(|v|
parse_accessor(&v)),
_ => {},
}
}
}
for i in 0..comment.num_children() {
self.parse(&comment.get_child(i).unwrap(), matched);
}
}
}