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