ligen_core/ir/
path.rs

1use crate::ir::Identifier;
2use quote::ToTokens;
3use quote::TokenStreamExt;
4use quote::quote;
5use proc_macro2::TokenStream;
6
7/// A fully qualified path.
8#[derive(Debug, Clone, PartialEq)]
9pub struct Path {
10    /// The path segments.
11    pub segments: Vec<Identifier>
12}
13
14impl Path {
15    /// Get the last segment of the path.
16    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}