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