cainome_parser/tokens/
array.rs1use super::constants::CAIRO_CORE_SPAN_ARRAY;
2use super::genericity;
3
4use crate::tokens::Token;
5use crate::{CainomeResult, Error};
6
7pub const CAIRO_0_ARRAY: &str = "*";
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Array {
11 pub type_path: String,
12 pub inner: Box<Token>,
13 pub is_legacy: bool,
14}
15
16impl Array {
17 pub fn parse(type_path: &str) -> CainomeResult<Self> {
18 for a in CAIRO_CORE_SPAN_ARRAY {
19 if type_path.starts_with(a) {
20 let generic_args = genericity::extract_generics_args(type_path)?;
21
22 if generic_args.len() != 1 {
23 return Err(Error::TokenInitFailed(format!(
24 "Array/Span are expected exactly one generic argument, found {} in `{}`.",
25 generic_args.len(),
26 type_path,
27 )));
28 }
29
30 let (_, generic_arg_token) = &generic_args[0];
31
32 return Ok(Self {
33 type_path: type_path.to_string(),
34 inner: Box::new(generic_arg_token.clone()),
35 is_legacy: false,
36 });
37 }
38 }
39
40 if let Some(inner_type) = type_path.strip_suffix(CAIRO_0_ARRAY) {
41 return Ok(Self {
42 type_path: type_path.to_string(),
43 inner: Box::new(Token::parse(inner_type)?),
44 is_legacy: true,
45 });
46 }
47
48 Err(Error::TokenInitFailed(format!(
49 "Array/Span couldn't be initialized from `{}`.",
50 type_path,
51 )))
52 }
53
54 pub fn resolve_generic(&self, generic_name: &str, generic_type_path: &str) -> Token {
55 if self.type_path == generic_type_path {
56 Token::GenericArg(generic_name.to_string())
57 } else {
58 Token::Array(Self {
59 type_path: self.type_path.clone(),
60 inner: Box::new(self.inner.resolve_generic(generic_name, generic_type_path)),
61 is_legacy: self.is_legacy,
62 })
63 }
64 }
65
66 pub fn apply_alias(&mut self, type_path: &str, alias: &str) {
67 self.inner.apply_alias(type_path, alias);
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use crate::tokens::*;
75
76 #[test]
77 fn test_parse() {
78 assert_eq!(
79 Array::parse("core::array::Array::<core::felt252>").unwrap(),
80 Array {
81 type_path: "core::array::Array::<core::felt252>".to_string(),
82 inner: Box::new(Token::CoreBasic(CoreBasic {
83 type_path: "core::felt252".to_string()
84 })),
85 is_legacy: false,
86 }
87 );
88 }
89
90 #[test]
91 fn test_parse_no_inner_invalid() {
92 assert!(Array::parse("core::array::Array").is_err());
93 assert!(Array::parse("core::array::Array<>").is_err());
94 }
95
96 #[test]
97 fn test_parse_wrong_path_invalid() {
98 assert!(Array::parse("array::Array::<core::felt252>").is_err());
99 }
100
101 #[test]
102 fn test_parse_invalid_path_invalid() {
103 assert!(Array::parse("module::module2::array::Array::<core::felt252>").is_err());
104 assert!(Array::parse("module::module2::MyStruct::<core::felt252>").is_err());
105 }
106}