cainome_parser/abi/
parser_legacy.rs1use starknet::core::types::contract::legacy::{
2 RawLegacyAbiEntry, RawLegacyMember, RawLegacyStruct,
3};
4use starknet::core::types::contract::StateMutability;
5use std::collections::HashMap;
6
7use crate::tokens::{Composite, CompositeType, CoreBasic, Function, Token};
8use crate::{CainomeResult, Error, TokenizedAbi};
9
10pub struct AbiParserLegacy {}
11
12impl AbiParserLegacy {
13 pub fn tokens_from_abi_string(
20 abi: &str,
21 type_aliases: &HashMap<String, String>,
22 ) -> CainomeResult<TokenizedAbi> {
23 let abi_entries = Self::parse_abi_string(abi)?;
24 let tokenized_abi =
25 Self::collect_tokens(&abi_entries, type_aliases).expect("failed tokens parsing");
26
27 Ok(tokenized_abi)
28 }
29
30 pub fn parse_abi_string(abi: &str) -> CainomeResult<Vec<RawLegacyAbiEntry>> {
36 let entries =
37 serde_json::from_str::<Vec<RawLegacyAbiEntry>>(abi).map_err(Error::SerdeJson)?;
38 Ok(entries)
39 }
40
41 pub fn collect_tokens(
43 entries: &[RawLegacyAbiEntry],
44 type_aliases: &HashMap<String, String>,
45 ) -> CainomeResult<TokenizedAbi> {
46 let mut tokens: HashMap<String, Token> = HashMap::new();
47
48 for entry in entries {
49 Self::collect_entry_token(entry, &mut tokens)?;
50 }
51
52 let mut structs = vec![];
53 let mut enums = vec![];
54 let mut all_composites: HashMap<String, Composite> = HashMap::new();
58
59 for (_, mut t) in tokens {
61 for (type_path, alias) in type_aliases {
62 t.apply_alias(type_path, alias);
63 }
64
65 if let Token::Composite(ref c) = t {
66 all_composites.insert(c.type_path_no_generic(), c.clone());
67
68 match c.r#type {
69 CompositeType::Struct => structs.push(t),
70 CompositeType::Enum => enums.push(t),
71 _ => (),
72 }
73 }
74 }
75
76 let mut functions = vec![];
77
78 for entry in entries {
79 Self::collect_entry_function(entry, &mut all_composites, &mut structs, &mut functions)?;
80 }
81
82 let interfaces: HashMap<String, Vec<Token>> = HashMap::new();
83
84 Ok(TokenizedAbi {
85 enums,
86 structs,
87 functions,
88 interfaces,
89 })
90 }
91
92 fn collect_entry_token(
99 entry: &RawLegacyAbiEntry,
100 tokens: &mut HashMap<String, Token>,
101 ) -> CainomeResult<()> {
102 match entry {
103 RawLegacyAbiEntry::Struct(s) => {
104 if CoreBasic::parse(&s.name).is_ok() {
106 return Ok(());
107 };
108
109 let token: Token = s.try_into()?;
110 tokens.insert(token.type_path(), token);
111 }
112 RawLegacyAbiEntry::Event(ev) => {
113 let token: Token = ev.try_into()?;
114 tokens.insert(token.type_path(), token);
115 }
116 _ => (),
117 };
118
119 Ok(())
120 }
121
122 fn collect_entry_function(
131 entry: &RawLegacyAbiEntry,
132 all_composites: &mut HashMap<String, Composite>,
133 structs: &mut Vec<Token>,
134 functions: &mut Vec<Token>,
135 ) -> CainomeResult<()> {
136 fn get_existing_token_or_parsed(
139 type_path: &str,
140 all_composites: &HashMap<String, Composite>,
141 ) -> CainomeResult<Token> {
142 let parsed_token = Token::parse(type_path)?;
143
144 if let Token::Composite(ref c) = parsed_token {
148 match all_composites.get(&c.type_path_no_generic()) {
149 Some(e) => Ok(Token::Composite(e.clone())),
150 None => Ok(parsed_token),
151 }
152 } else {
153 Ok(parsed_token)
154 }
155 }
156
157 if let RawLegacyAbiEntry::Function(f) = entry {
160 let mutability = match f.state_mutability {
162 Some(_) => StateMutability::View,
163 None => StateMutability::External,
164 };
165
166 let mut func = Function::new(&f.name, mutability.into());
167
168 for i in &f.inputs {
169 let token = get_existing_token_or_parsed(&i.r#type, all_composites)?;
170 func.inputs.push((i.name.clone(), token));
171 }
172
173 for o in &f.outputs {
174 let token = get_existing_token_or_parsed(&o.r#type, all_composites)?;
175 func.named_outputs.push((o.name.clone(), token));
176 }
177
178 if !func.named_outputs.is_empty() {
179 let mut members = vec![];
180
181 for (offset, (n, t)) in func.named_outputs.iter().enumerate() {
182 members.push(RawLegacyMember {
183 name: n.clone(),
184 offset: offset.try_into().unwrap(),
185 r#type: t.type_path().clone(),
186 });
187 }
188
189 let s = RawLegacyStruct {
190 members,
191 name: func.get_cairo0_output_name(),
192 size: func.named_outputs.len() as u64,
193 };
194
195 structs.push((&s).try_into()?);
196 }
197
198 functions.push(Token::Function(func));
199 }
200
201 Ok(())
202 }
203}