diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/bindgen/ir/annotations.rs | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/bindgen/ir/annotations.rs')
-rw-r--r-- | third_party/rust/bindgen/ir/annotations.rs | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/third_party/rust/bindgen/ir/annotations.rs b/third_party/rust/bindgen/ir/annotations.rs new file mode 100644 index 0000000000..288c11ebae --- /dev/null +++ b/third_party/rust/bindgen/ir/annotations.rs @@ -0,0 +1,211 @@ +//! 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, Eq, 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(Default, Clone, PartialEq, Eq, 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 to add a #[must_use] annotation to this type. + must_use_type: 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 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_deref() + } + + /// 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 this type get a `#[must_use]` annotation? + pub fn must_use_type(&self) -> bool { + self.must_use_type + } + + /// 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, + "mustusetype" => self.must_use_type = 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 + } +} |