bindgen/ir/
module.rs

1//! Intermediate representation for modules (AKA C++ namespaces).
2
3use super::context::BindgenContext;
4use super::dot::DotAttributes;
5use super::item::ItemSet;
6use crate::clang;
7use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
8use crate::parse_one;
9
10use std::io;
11
12/// Whether this module is inline or not.
13#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14pub(crate) enum ModuleKind {
15    /// This module is not inline.
16    Normal,
17    /// This module is inline, as in `inline namespace foo {}`.
18    Inline,
19}
20
21/// A module, as in, a C++ namespace.
22#[derive(Clone, Debug)]
23pub(crate) struct Module {
24    /// The name of the module, or none if it's anonymous.
25    name: Option<String>,
26    /// The kind of module this is.
27    kind: ModuleKind,
28    /// The children of this module, just here for convenience.
29    children: ItemSet,
30}
31
32impl Module {
33    /// Construct a new `Module`.
34    pub(crate) fn new(name: Option<String>, kind: ModuleKind) -> Self {
35        Module {
36            name,
37            kind,
38            children: ItemSet::new(),
39        }
40    }
41
42    /// Get this module's name.
43    pub(crate) fn name(&self) -> Option<&str> {
44        self.name.as_deref()
45    }
46
47    /// Get a mutable reference to this module's children.
48    pub(crate) fn children_mut(&mut self) -> &mut ItemSet {
49        &mut self.children
50    }
51
52    /// Get this module's children.
53    pub(crate) fn children(&self) -> &ItemSet {
54        &self.children
55    }
56
57    /// Whether this namespace is inline.
58    pub(crate) fn is_inline(&self) -> bool {
59        self.kind == ModuleKind::Inline
60    }
61}
62
63impl DotAttributes for Module {
64    fn dot_attributes<W>(
65        &self,
66        _ctx: &BindgenContext,
67        out: &mut W,
68    ) -> io::Result<()>
69    where
70        W: io::Write,
71    {
72        writeln!(out, "<tr><td>ModuleKind</td><td>{:?}</td></tr>", self.kind)
73    }
74}
75
76impl ClangSubItemParser for Module {
77    fn parse(
78        cursor: clang::Cursor,
79        ctx: &mut BindgenContext,
80    ) -> Result<ParseResult<Self>, ParseError> {
81        use clang_sys::*;
82        match cursor.kind() {
83            CXCursor_Namespace => {
84                let module_id = ctx.module(cursor);
85                ctx.with_module(module_id, |ctx| {
86                    cursor.visit_sorted(ctx, |ctx, child| {
87                        parse_one(ctx, child, Some(module_id.into()));
88                    });
89                });
90
91                Ok(ParseResult::AlreadyResolved(module_id.into()))
92            }
93            _ => Err(ParseError::Continue),
94        }
95    }
96}