blob: 96f07c19e07ad61020781d17643bc3bebdfbf10f [file] [log] [blame]
David Tolnay6c9a6222020-09-06 23:08:57 -07001use syn::ext::IdentExt;
David Tolnaydd26bd02020-09-06 23:00:17 -07002use syn::parse::{ParseStream, Result};
David Tolnaybef9e6d2020-09-06 23:20:52 -07003use syn::{Ident, LitStr, Token};
David Tolnaydd26bd02020-09-06 23:00:17 -07004
5pub struct QualifiedName {
6 pub segments: Vec<Ident>,
7}
8
9impl QualifiedName {
10 pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
David Tolnay6c9a6222020-09-06 23:08:57 -070011 let mut segments = Vec::new();
12 let mut trailing_punct = true;
David Tolnaya23d7fd2020-12-04 12:21:27 -080013 let leading_colons: Option<Token![::]> = input.parse()?;
David Tolnay6c9a6222020-09-06 23:08:57 -070014 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 }
David Tolnaya23d7fd2020-12-04 12:21:27 -080020 if segments.is_empty() && leading_colons.is_none() {
David Tolnay6c9a6222020-09-06 23:08:57 -070021 return Err(input.error("expected path"));
22 } else if trailing_punct {
23 return Err(input.error("expected path segment"));
David Tolnaydd26bd02020-09-06 23:00:17 -070024 }
25 Ok(QualifiedName { segments })
26 }
David Tolnaybef9e6d2020-09-06 23:20:52 -070027
28 pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> {
29 if input.peek(LitStr) {
30 let lit: LitStr = input.parse()?;
David Tolnaya23d7fd2020-12-04 12:21:27 -080031 if lit.value().is_empty() {
32 let segments = Vec::new();
33 Ok(QualifiedName { segments })
34 } else {
35 lit.parse_with(Self::parse_unquoted)
36 }
David Tolnaybef9e6d2020-09-06 23:20:52 -070037 } else {
38 Self::parse_unquoted(input)
39 }
40 }
David Tolnaydd26bd02020-09-06 23:00:17 -070041}