1 use syn::ext::IdentExt; 2 use syn::parse::{ParseStream, Result}; 3 use syn::{Ident, LitStr, Token}; 4 5 pub struct QualifiedName { 6 pub segments: Vec<Ident>, 7 } 8 9 impl QualifiedName { parse_unquoted(input: ParseStream) -> Result<Self>10 pub fn parse_unquoted(input: ParseStream) -> Result<Self> { 11 let mut segments = Vec::new(); 12 let mut trailing_punct = true; 13 let leading_colons: Option<Token![::]> = input.parse()?; 14 while trailing_punct && input.peek(Ident::peek_any) { 15 let ident = Ident::parse_any(input)?; 16 segments.push(ident); 17 let colons: Option<Token![::]> = input.parse()?; 18 trailing_punct = colons.is_some(); 19 } 20 if segments.is_empty() && leading_colons.is_none() { 21 return Err(input.error("expected path")); 22 } else if trailing_punct { 23 return Err(input.error("expected path segment")); 24 } 25 Ok(QualifiedName { segments }) 26 } 27 parse_quoted_or_unquoted(input: ParseStream) -> Result<Self>28 pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> { 29 if input.peek(LitStr) { 30 let lit: LitStr = input.parse()?; 31 if lit.value().is_empty() { 32 let segments = Vec::new(); 33 Ok(QualifiedName { segments }) 34 } else { 35 lit.parse_with(Self::parse_unquoted) 36 } 37 } else { 38 Self::parse_unquoted(input) 39 } 40 } 41 } 42