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: ModuleId = ctx.module(cursor);
85 ctx.with_module(module_id, |ctx: &mut BindgenContext| {
86 cursor.visit_sorted(ctx, |ctx: &mut BindgenContext, child: Cursor| {
87 parse_one(ctx, cursor:child, parent:Some(module_id.into()))
88 })
89 });
90
91 Ok(ParseResult::AlreadyResolved(module_id.into()))
92 }
93 _ => Err(ParseError::Continue),
94 }
95 }
96}
97