133d722a9Sopenharmony_ciuse syn::ext::IdentExt; 233d722a9Sopenharmony_ciuse syn::parse::{Error, ParseStream, Result}; 333d722a9Sopenharmony_ciuse syn::{Ident, LitStr, Token}; 433d722a9Sopenharmony_ci 533d722a9Sopenharmony_cipub struct QualifiedName { 633d722a9Sopenharmony_ci pub segments: Vec<Ident>, 733d722a9Sopenharmony_ci} 833d722a9Sopenharmony_ci 933d722a9Sopenharmony_ciimpl QualifiedName { 1033d722a9Sopenharmony_ci pub fn parse_quoted(lit: &LitStr) -> Result<Self> { 1133d722a9Sopenharmony_ci if lit.value().is_empty() { 1233d722a9Sopenharmony_ci let segments = Vec::new(); 1333d722a9Sopenharmony_ci Ok(QualifiedName { segments }) 1433d722a9Sopenharmony_ci } else { 1533d722a9Sopenharmony_ci lit.parse_with(|input: ParseStream| { 1633d722a9Sopenharmony_ci let allow_raw = false; 1733d722a9Sopenharmony_ci parse_unquoted(input, allow_raw) 1833d722a9Sopenharmony_ci }) 1933d722a9Sopenharmony_ci } 2033d722a9Sopenharmony_ci } 2133d722a9Sopenharmony_ci 2233d722a9Sopenharmony_ci pub fn parse_unquoted(input: ParseStream) -> Result<Self> { 2333d722a9Sopenharmony_ci let allow_raw = true; 2433d722a9Sopenharmony_ci parse_unquoted(input, allow_raw) 2533d722a9Sopenharmony_ci } 2633d722a9Sopenharmony_ci 2733d722a9Sopenharmony_ci pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> { 2833d722a9Sopenharmony_ci if input.peek(LitStr) { 2933d722a9Sopenharmony_ci let lit: LitStr = input.parse()?; 3033d722a9Sopenharmony_ci Self::parse_quoted(&lit) 3133d722a9Sopenharmony_ci } else { 3233d722a9Sopenharmony_ci Self::parse_unquoted(input) 3333d722a9Sopenharmony_ci } 3433d722a9Sopenharmony_ci } 3533d722a9Sopenharmony_ci} 3633d722a9Sopenharmony_ci 3733d722a9Sopenharmony_cifn parse_unquoted(input: ParseStream, allow_raw: bool) -> Result<QualifiedName> { 3833d722a9Sopenharmony_ci let mut segments = Vec::new(); 3933d722a9Sopenharmony_ci let mut trailing_punct = true; 4033d722a9Sopenharmony_ci let leading_colons: Option<Token![::]> = input.parse()?; 4133d722a9Sopenharmony_ci while trailing_punct && input.peek(Ident::peek_any) { 4233d722a9Sopenharmony_ci let mut ident = Ident::parse_any(input)?; 4333d722a9Sopenharmony_ci if let Some(unraw) = ident.to_string().strip_prefix("r#") { 4433d722a9Sopenharmony_ci if !allow_raw { 4533d722a9Sopenharmony_ci let msg = format!( 4633d722a9Sopenharmony_ci "raw identifier `{}` is not allowed in a quoted namespace; use `{}`, or remove quotes", 4733d722a9Sopenharmony_ci ident, unraw, 4833d722a9Sopenharmony_ci ); 4933d722a9Sopenharmony_ci return Err(Error::new(ident.span(), msg)); 5033d722a9Sopenharmony_ci } 5133d722a9Sopenharmony_ci ident = Ident::new(unraw, ident.span()); 5233d722a9Sopenharmony_ci } 5333d722a9Sopenharmony_ci segments.push(ident); 5433d722a9Sopenharmony_ci let colons: Option<Token![::]> = input.parse()?; 5533d722a9Sopenharmony_ci trailing_punct = colons.is_some(); 5633d722a9Sopenharmony_ci } 5733d722a9Sopenharmony_ci if segments.is_empty() && leading_colons.is_none() { 5833d722a9Sopenharmony_ci return Err(input.error("expected path")); 5933d722a9Sopenharmony_ci } else if trailing_punct { 6033d722a9Sopenharmony_ci return Err(input.error("expected path segment")); 6133d722a9Sopenharmony_ci } 6233d722a9Sopenharmony_ci Ok(QualifiedName { segments }) 6333d722a9Sopenharmony_ci} 64