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