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