blob: 12664f602229cf572682e71e9084ad0d44d22dec [file] [log] [blame]
//! 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 crate::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.
///
/// You can see the kind of comments that are accepted in the Doxygen
/// documentation:
///
/// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
#[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, or enum variants.
hide: bool,
/// Whether this type should be replaced by another. The name is a
/// namespace-aware path.
use_instead_of: Option<Vec<String>>,
/// Manually disable deriving copy/clone on this type. Only applies to
/// struct or union types.
disallow_copy: bool,
/// Manually disable deriving debug on this type.
disallow_debug: bool,
/// Manually disable deriving/implement default on this type.
disallow_default: 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>,
/// Whether this enum variant should be constified.
///
/// This is controlled by the `constant` attribute, this way:
///
/// ```cpp
/// enum Foo {
/// Bar = 0, /**< <div rustbindgen constant></div> */
/// Baz = 0,
/// };
/// ```
///
/// In that case, bindgen will generate a constant for `Bar` instead of
/// `Baz`.
constify_enum_variant: bool,
/// List of explicit derives for this type.
derives: Vec<String>,
}
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,
disallow_debug: false,
disallow_default: false,
private_fields: None,
accessor_kind: None,
constify_enum_variant: false,
derives: vec![],
}
}
}
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<&[String]> {
self.use_instead_of.as_ref().map(|s| &**s)
}
/// The list of derives that have been specified in this annotation.
pub fn derives(&self) -> &[String] {
&self.derives
}
/// Should we avoid implementing the `Copy` trait?
pub fn disallow_copy(&self) -> bool {
self.disallow_copy
}
/// Should we avoid implementing the `Debug` trait?
pub fn disallow_debug(&self) -> bool {
self.disallow_debug
}
/// Should we avoid implementing the `Default` trait?
pub fn disallow_default(&self) -> bool {
self.disallow_default
}
/// 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 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,
"nodebug" => self.disallow_debug = true,
"nodefault" => self.disallow_default = true,
"replaces" => {
self.use_instead_of = Some(
attr.value.split("::").map(Into::into).collect(),
)
}
"derive" => self.derives.push(attr.value),
"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);
}
}
/// Returns whether we've parsed a "constant" attribute.
pub fn constify_enum_variant(&self) -> bool {
self.constify_enum_variant
}
}