1use crate::ir::Identifier;
2use quote::ToTokens;
3use quote::TokenStreamExt;
4use quote::quote;
5use proc_macro2::TokenStream;
6
7#[derive(Debug, Clone, PartialEq)]
9pub struct Path {
10 pub segments: Vec<Identifier>
12}
13
14impl Path {
15 pub fn last(&self) -> Identifier {
17 self.segments.last().unwrap().clone()
18 }
19}
20
21impl From<&str> for Path {
22 fn from(string: &str) -> Path {
23 let segments = string
24 .split("::")
25 .into_iter()
26 .map(|segment| Identifier::new(segment))
27 .collect();
28 Self { segments }
29 }
30}
31
32impl From<String> for Path {
33 fn from(string: String) -> Path {
34 string.as_str().into()
35 }
36}
37
38impl From<syn::Path> for Path {
39 fn from(path: syn::Path) -> Self {
40 let segments = path
41 .segments
42 .iter()
43 .map(|segment| segment.ident.clone().into())
44 .collect();
45 Self { segments }
46 }
47}
48
49impl From<Identifier> for Path {
50 fn from(identifier: Identifier) -> Self {
51 let segments = vec![identifier];
52 Self { segments }
53 }
54}
55
56impl From<syn::Ident> for Path {
57 fn from(identifier: syn::Ident) -> Self {
58 let segments = vec![identifier.into()];
59 Self { segments }
60 }
61}
62
63impl ToTokens for Path {
64 fn to_tokens(&self, tokens: &mut TokenStream) {
65 let mut segments = self.segments.iter();
66 tokens.append_all(segments.next().unwrap().to_token_stream());
67 for segment in segments {
68 tokens.append_all(quote! { ::#segment })
69 }
70 }
71}
72
73#[cfg(test)]
74mod test {
75 use quote::quote;
76 use syn::parse_quote::parse;
77 use crate::ir::Path;
78 use crate::ir::Identifier;
79
80 #[test]
81 fn identifier_as_path() {
82 let path: Path = parse::<syn::Path>(quote! { u8 }).into();
83 assert_eq!(path.segments.first(), Some(&Identifier::new("u8")));
84 }
85
86 #[test]
87 fn path() {
88 let path: Path = parse::<syn::Path>(quote! { std::convert::TryFrom }).into();
89 let segments: Vec<_> = vec!["std", "convert", "TryFrom"].into_iter().map(Identifier::from).collect();
90 assert_eq!(path.segments, segments);
91 }
92
93 #[test]
94 fn path_from_string() {
95 let path: Path = "std::convert::TryFrom".into();
96 let segments: Vec<_> = vec!["std", "convert", "TryFrom"].into_iter().map(Identifier::from).collect();
97 assert_eq!(path.segments, segments);
98 }
99
100}