blob: 41a38dd7a63bfb2e200550451e21fc2e319be36d [file] [log] [blame]
David Tolnaydd26bd02020-09-06 23:00:17 -07001use crate::syntax::qualified::QualifiedName;
David Tolnay60e7aa62020-11-01 12:34:51 -08002use crate::syntax::Api;
Adrian Taylor7827d782020-10-29 22:03:34 -07003#[cfg(test)]
4use proc_macro2::Span;
David Tolnayb6cf3142020-04-19 20:56:09 -07005use quote::IdentFragment;
David Tolnay754e21c2020-03-29 20:58:46 -07006use std::fmt::{self, Display};
7use std::slice::Iter;
David Tolnayb6cf3142020-04-19 20:56:09 -07008use syn::parse::{Parse, ParseStream, Result};
David Tolnaydd26bd02020-09-06 23:00:17 -07009use syn::{Ident, Token};
David Tolnayb6cf3142020-04-19 20:56:09 -070010
11mod kw {
12 syn::custom_keyword!(namespace);
13}
David Tolnay754e21c2020-03-29 20:58:46 -070014
15#[derive(Clone)]
16pub struct Namespace {
David Tolnay63f92e82020-04-30 20:40:20 -070017 segments: Vec<Ident>,
David Tolnay754e21c2020-03-29 20:58:46 -070018}
19
20impl Namespace {
David Tolnayb6cf3142020-04-19 20:56:09 -070021 pub fn none() -> Self {
22 Namespace {
23 segments: Vec::new(),
24 }
David Tolnay754e21c2020-03-29 20:58:46 -070025 }
26
David Tolnay63f92e82020-04-30 20:40:20 -070027 pub fn iter(&self) -> Iter<Ident> {
David Tolnay754e21c2020-03-29 20:58:46 -070028 self.segments.iter()
29 }
Adrian Taylor3e5cff42020-10-29 19:48:45 -070030
31 pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Namespace> {
32 if input.is_empty() {
33 return Ok(Namespace::none());
34 }
35
36 input.parse::<kw::namespace>()?;
37 input.parse::<Token![=]>()?;
38 let ns = input.parse::<Namespace>()?;
39 input.parse::<Option<Token![,]>>()?;
40 Ok(ns)
41 }
Adrian Taylor7827d782020-10-29 22:03:34 -070042
43 #[cfg(test)]
44 pub fn from_str(ns: &str) -> Self {
45 Namespace {
46 segments: ns
47 .split("::")
48 .map(|x| Ident::new(x, Span::call_site()))
49 .collect(),
50 }
51 }
David Tolnay754e21c2020-03-29 20:58:46 -070052}
53
David Tolnayb6cf3142020-04-19 20:56:09 -070054impl Parse for Namespace {
55 fn parse(input: ParseStream) -> Result<Self> {
Adrian Taylor3e5cff42020-10-29 19:48:45 -070056 let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
David Tolnayb6cf3142020-04-19 20:56:09 -070057 Ok(Namespace { segments })
58 }
59}
60
David Tolnay754e21c2020-03-29 20:58:46 -070061impl Display for Namespace {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 for segment in self {
David Tolnay63f92e82020-04-30 20:40:20 -070064 write!(f, "{}$", segment)?;
David Tolnay754e21c2020-03-29 20:58:46 -070065 }
66 Ok(())
67 }
68}
69
David Tolnayb6cf3142020-04-19 20:56:09 -070070impl IdentFragment for Namespace {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 Display::fmt(self, f)
73 }
74}
75
David Tolnay754e21c2020-03-29 20:58:46 -070076impl<'a> IntoIterator for &'a Namespace {
David Tolnay63f92e82020-04-30 20:40:20 -070077 type Item = &'a Ident;
78 type IntoIter = Iter<'a, Ident>;
David Tolnay754e21c2020-03-29 20:58:46 -070079 fn into_iter(self) -> Self::IntoIter {
80 self.iter()
81 }
82}
David Tolnay60e7aa62020-11-01 12:34:51 -080083
84impl Api {
85 pub fn get_namespace(&self) -> Option<&Namespace> {
86 match self {
87 Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
88 Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
89 Api::Enum(enm) => Some(&enm.ident.cxx.ns),
90 Api::Struct(strct) => Some(&strct.ident.cxx.ns),
91 Api::RustType(rty) => Some(&rty.ident.cxx.ns),
92 Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
93 Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
94 }
95 }
96}