cxx_build/syntax/
namespace.rs1use crate::syntax::qualified::QualifiedName;
2use std::slice::Iter;
3use syn::parse::{Error, Parse, ParseStream, Result};
4use syn::{Expr, Ident, Lit, Meta, Token};
5
6mod kw {
7 syn::custom_keyword!(namespace);
8}
9
10#[derive(Clone, Default, PartialEq)]
11pub(crate) struct Namespace {
12 segments: Vec<Ident>,
13}
14
15impl Namespace {
16 pub(crate) const ROOT: Self = Namespace {
17 segments: Vec::new(),
18 };
19
20 pub(crate) fn iter(&self) -> Iter<Ident> {
21 self.segments.iter()
22 }
23
24 pub(crate) fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Self> {
25 if input.is_empty() {
26 return Ok(Namespace::ROOT);
27 }
28
29 input.parse::<kw::namespace>()?;
30 input.parse::<Token![=]>()?;
31 let namespace = input.parse::<Namespace>()?;
32 input.parse::<Option<Token![,]>>()?;
33 Ok(namespace)
34 }
35
36 pub(crate) fn parse_meta(meta: &Meta) -> Result<Self> {
37 if let Meta::NameValue(meta) = meta {
38 match &meta.value {
39 Expr::Lit(expr) => {
40 if let Lit::Str(lit) = &expr.lit {
41 let segments = QualifiedName::parse_quoted(lit)?.segments;
42 return Ok(Namespace { segments });
43 }
44 }
45 Expr::Path(expr)
46 if expr.qself.is_none()
47 && expr
48 .path
49 .segments
50 .iter()
51 .all(|segment| segment.arguments.is_none()) =>
52 {
53 let segments = expr
54 .path
55 .segments
56 .iter()
57 .map(|segment| segment.ident.clone())
58 .collect();
59 return Ok(Namespace { segments });
60 }
61 _ => {}
62 }
63 }
64 Err(Error::new_spanned(meta, "unsupported namespace attribute"))
65 }
66}
67
68impl Default for &Namespace {
69 fn default() -> Self {
70 const ROOT: &Namespace = &Namespace::ROOT;
71 ROOT
72 }
73}
74
75impl Parse for Namespace {
76 fn parse(input: ParseStream) -> Result<Self> {
77 let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
78 Ok(Namespace { segments })
79 }
80}
81
82impl<'a> IntoIterator for &'a Namespace {
83 type Item = &'a Ident;
84 type IntoIter = Iter<'a, Ident>;
85 fn into_iter(self) -> Self::IntoIter {
86 self.iter()
87 }
88}
89
90impl<'a> FromIterator<&'a Ident> for Namespace {
91 fn from_iter<I>(idents: I) -> Self
92 where
93 I: IntoIterator<Item = &'a Ident>,
94 {
95 let segments = idents.into_iter().cloned().collect();
96 Namespace { segments }
97 }
98}