blob: 415b2ef5849242c2edf5f281e0b3dc9b18b73637 [file] [log] [blame]
Brian Silverman4e662aa2022-05-11 23:10:19 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::ParseResult;
10use proc_macro2::Ident;
11use quote::{quote, ToTokens, TokenStreamExt};
12use syn::parse::{Parse, ParseStream};
13
14/// A little like [`syn::Path`] but simpler - contains only identifiers,
15/// no path arguments. Guaranteed to always have at least one identifier.
16#[derive(Debug, Clone, Hash, PartialEq, Eq)]
17pub struct RustPath(Vec<Ident>);
18
19impl RustPath {
20 pub fn new_from_ident(id: Ident) -> Self {
21 Self(vec![id])
22 }
23
24 #[must_use]
25 pub fn append(&self, id: Ident) -> Self {
26 Self(self.0.iter().cloned().chain(std::iter::once(id)).collect())
27 }
28
29 pub fn get_final_ident(&self) -> &Ident {
30 self.0.last().unwrap()
31 }
32
33 pub fn len(&self) -> usize {
34 self.0.len()
35 }
36
37 pub fn is_empty(&self) -> bool {
38 self.0.is_empty()
39 }
40}
41
42impl ToTokens for RustPath {
43 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
44 let mut it = self.0.iter();
45 let mut id = it.next();
46 while id.is_some() {
47 id.unwrap().to_tokens(tokens);
48 let next = it.next();
49 if next.is_some() {
50 tokens.append_all(quote! { :: });
51 }
52 id = next;
53 }
54 }
55}
56
57impl Parse for RustPath {
58 fn parse(input: ParseStream) -> ParseResult<Self> {
59 let id: Ident = input.parse()?;
60 let mut p = RustPath::new_from_ident(id);
61 while input.parse::<Option<syn::token::Colon2>>()?.is_some() {
62 let id: Ident = input.parse()?;
63 p = p.append(id);
64 }
65 Ok(p)
66 }
67}