aboutsummaryrefslogtreecommitdiff
path: root/syntax/qualified.rs
blob: 96f07c19e07ad61020781d17643bc3bebdfbf10f (plain)
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)
        }
    }
}