use clang;
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum FieldAccessorKind {
None,
Regular,
Unsafe,
Immutable,
}
#[derive(Clone, PartialEq, Debug)]
pub struct Annotations {
opaque: bool,
hide: bool,
use_instead_of: Option<Vec<String>>,
disallow_copy: bool,
private_fields: Option<bool>,
accessor_kind: Option<FieldAccessorKind>,
constify_enum_variant: bool,
}
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,
constify_enum_variant: false,
}
}
}
impl Annotations {
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 }
}
pub fn hide(&self) -> bool {
self.hide
}
pub fn opaque(&self) -> bool {
self.opaque
}
pub fn use_instead_of(&self) -> Option<&[String]> {
self.use_instead_of.as_ref().map(|s| &**s)
}
pub fn disallow_copy(&self) -> bool {
self.disallow_copy
}
pub fn private_fields(&self) -> Option<bool> {
self.private_fields
}
pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
self.accessor_kind
}
fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
use clang_sys::CXComment_HTMLStartTag;
if comment.kind() == CXComment_HTMLStartTag &&
comment.get_tag_name() == "div" &&
comment.get_tag_attrs()
.next()
.map_or(false, |attr| attr.name == "rustbindgen") {
*matched = true;
for attr in comment.get_tag_attrs() {
match attr.name.as_str() {
"opaque" => self.opaque = true,
"hide" => self.hide = true,
"nocopy" => self.disallow_copy = true,
"replaces" => {
self.use_instead_of = Some(attr.value
.split("::")
.map(Into::into)
.collect())
}
"private" => {
self.private_fields = Some(attr.value != "false")
}
"accessor" => {
self.accessor_kind = Some(parse_accessor(&attr.value))
}
"constant" => self.constify_enum_variant = true,
_ => {}
}
}
}
for child in comment.get_children() {
self.parse(&child, matched);
}
}
pub fn constify_enum_variant(&self) -> bool {
self.constify_enum_variant
}
}