cainome_parser/tokens/
tuple.rs

1use syn::Type;
2
3use super::Token;
4use crate::{CainomeResult, Error};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Tuple {
8    pub type_path: String,
9    pub inners: Vec<Token>,
10}
11
12impl Tuple {
13    pub fn parse(type_path: &str) -> CainomeResult<Self> {
14        let t: Type = syn::parse_str(type_path)?;
15
16        let mut inners = vec![];
17
18        match t {
19            Type::Tuple(t) => {
20                if t.elems.is_empty() {
21                    return Err(Error::TokenInitFailed(
22                        "Unit type `()` is considered as a CoreBasic, not a tuple.".to_string(),
23                    ));
24                }
25
26                for e in t.elems {
27                    let ty = quote::quote!(#e).to_string().replace(' ', "");
28                    inners.push(Token::parse(&ty)?);
29                }
30            }
31            Type::Paren(t) => {
32                // Tuple with one element are under `Paren` variant.
33                let e = t.elem;
34                let ty = quote::quote!(#e).to_string().replace(' ', "");
35                inners.push(Token::parse(&ty)?);
36            }
37            _ => {
38                return Err(Error::TokenInitFailed(format!(
39                    "Tuple couldn't be initialized from `{}`.",
40                    type_path,
41                )));
42            }
43        }
44
45        Ok(Self {
46            type_path: type_path.to_string(),
47            inners,
48        })
49    }
50
51    pub fn resolve_generic(&self, generic_name: &str, generic_type_path: &str) -> Token {
52        if self.type_path == generic_type_path {
53            Token::GenericArg(generic_name.to_string())
54        } else {
55            let mut inners = vec![];
56
57            for i in &self.inners {
58                inners.push(i.resolve_generic(generic_name, generic_type_path));
59            }
60
61            Token::Tuple(Self {
62                type_path: self.type_path.clone(),
63                inners,
64            })
65        }
66    }
67
68    pub fn apply_alias(&mut self, type_path: &str, alias: &str) {
69        for i in &mut self.inners {
70            i.apply_alias(type_path, alias);
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::tokens::*;
79
80    #[test]
81    fn test_parse_unit_invalid() {
82        assert!(Tuple::parse("()").is_err());
83    }
84
85    #[test]
86    fn test_parse_one_inner() {
87        assert_eq!(
88            Tuple::parse("(core::felt252)").unwrap(),
89            Tuple {
90                type_path: "(core::felt252)".to_string(),
91                inners: vec![Token::CoreBasic(CoreBasic {
92                    type_path: "core::felt252".to_string()
93                }),],
94            }
95        );
96    }
97
98    #[test]
99    fn test_parse_multiple_inners() {
100        assert_eq!(
101            Tuple::parse("(core::felt252, core::integer::u64)").unwrap(),
102            Tuple {
103                type_path: "(core::felt252, core::integer::u64)".to_string(),
104                inners: vec![
105                    Token::CoreBasic(CoreBasic {
106                        type_path: "core::felt252".to_string()
107                    }),
108                    Token::CoreBasic(CoreBasic {
109                        type_path: "core::integer::u64".to_string()
110                    }),
111                ],
112            }
113        );
114    }
115
116    #[test]
117    fn test_parse_other_type_invalid() {
118        assert!(Tuple::parse("module::module2::MyStuct").is_err());
119        assert!(Tuple::parse("core::integer::u64").is_err());
120    }
121}