Skip to content

Commit c871343

Browse files
committed
Allow namespace override.
This change allows a #[namespace (namespace = A::B)] attribute for each item in a cxx::bridge. We now have a fair number of different types of name floating around: * C++ identifiers * C++ fully-qualified names * Rust identifiers * Rust fully-qualified names (future, when we support sub-modules) * Items with both a Rust and C++ name (a 'Pair') * Types with only a known Rust name, which can be resolved to a C++ name. This change attempts to put some sensible names for all these things in syntax/mod.rs, and so that would be a good place to start review. At the moment, the Namespace (included in each CppName) is ruthlessly cloned all over the place. As a given namespace is likely to be applicable to many types and functions, it may save significant memory in future to use Rc<> here. But let's not optimise too early.
1 parent 0fac321 commit c871343

18 files changed

+757
-448
lines changed

gen/src/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub(super) mod error;
55
mod file;
66
pub(super) mod fs;
77
pub(super) mod include;
8+
mod namespace_organizer;
89
pub(super) mod out;
910
mod write;
1011

@@ -109,22 +110,22 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
109110
.ok_or(Error::NoBridgeMod)?;
110111
let ref namespace = bridge.namespace;
111112
let trusted = bridge.unsafety.is_some();
112-
let ref apis = syntax::parse_items(errors, bridge.content, trusted);
113+
let ref apis = syntax::parse_items(errors, bridge.content, trusted, namespace);
113114
let ref types = Types::collect(errors, apis);
114115
errors.propagate()?;
115-
check::typecheck(errors, namespace, apis, types);
116+
check::typecheck(errors, apis, types);
116117
errors.propagate()?;
117118
// Some callers may wish to generate both header and C++
118119
// from the same token stream to avoid parsing twice. But others
119120
// only need to generate one or the other.
120121
Ok(GeneratedCode {
121122
header: if opt.gen_header {
122-
write::gen(namespace, apis, types, opt, true).content()
123+
write::gen(apis, types, opt, true).content()
123124
} else {
124125
Vec::new()
125126
},
126127
implementation: if opt.gen_implementation {
127-
write::gen(namespace, apis, types, opt, false).content()
128+
write::gen(apis, types, opt, false).content()
128129
} else {
129130
Vec::new()
130131
},

gen/src/namespace_organizer.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use crate::syntax::Api;
2+
use proc_macro2::Ident;
3+
use std::collections::BTreeMap;
4+
5+
pub(crate) struct NamespaceEntries<'a> {
6+
pub(crate) entries: Vec<&'a Api>,
7+
pub(crate) children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
8+
}
9+
10+
pub(crate) fn sort_by_namespace(apis: &[Api]) -> NamespaceEntries {
11+
let api_refs = apis.iter().collect::<Vec<_>>();
12+
sort_by_inner_namespace(api_refs, 0)
13+
}
14+
15+
fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
16+
let mut root = NamespaceEntries {
17+
entries: Vec::new(),
18+
children: BTreeMap::new(),
19+
};
20+
21+
let mut kids_by_child_ns = BTreeMap::new();
22+
for api in apis {
23+
if let Some(ns) = api.get_namespace() {
24+
let first_ns_elem = ns.iter().nth(depth);
25+
if let Some(first_ns_elem) = first_ns_elem {
26+
let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
27+
list.push(api);
28+
continue;
29+
}
30+
}
31+
root.entries.push(api);
32+
}
33+
34+
for (k, v) in kids_by_child_ns.into_iter() {
35+
root.children
36+
.insert(k, sort_by_inner_namespace(v, depth + 1));
37+
}
38+
39+
root
40+
}

gen/src/out.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use crate::gen::include::Includes;
2-
use crate::syntax::namespace::Namespace;
32
use std::cell::RefCell;
43
use std::fmt::{self, Arguments, Write};
54

65
pub(crate) struct OutFile {
7-
pub namespace: Namespace,
86
pub header: bool,
97
pub include: Includes,
108
pub front: Content,
@@ -18,9 +16,8 @@ pub struct Content {
1816
}
1917

2018
impl OutFile {
21-
pub fn new(namespace: Namespace, header: bool) -> Self {
19+
pub fn new(header: bool) -> Self {
2220
OutFile {
23-
namespace,
2421
header,
2522
include: Includes::new(),
2623
front: Content::new(),

0 commit comments

Comments
 (0)