forked from cartridge-gg/cainome
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
203 lines (186 loc) · 6.9 KB
/
Copy pathmod.rs
File metadata and controls
203 lines (186 loc) · 6.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//! Cairo ABI tokens.
//!
//! TODO.
mod array;
mod basic;
mod composite;
mod constants;
mod function;
mod genericity;
mod tuple;
use std::collections::HashMap;
pub use array::Array;
pub use basic::CoreBasic;
pub use composite::{Composite, CompositeInner, CompositeInnerKind, CompositeType};
pub use function::{Function, FunctionOutputKind, StateMutability};
pub use tuple::Tuple;
use crate::{CainomeResult, Error};
#[derive(Debug, Clone, PartialEq)]
pub enum Token {
CoreBasic(CoreBasic),
Array(Array),
Tuple(Tuple),
Composite(Composite),
GenericArg(String),
Function(Function),
}
impl Token {
pub fn parse(type_path: &str) -> CainomeResult<Self> {
if let Ok(b) = CoreBasic::parse(type_path) {
return Ok(Token::CoreBasic(b));
}
if let Ok(a) = Array::parse(type_path) {
return Ok(Token::Array(a));
}
if let Ok(t) = Tuple::parse(type_path) {
return Ok(Token::Tuple(t));
}
if let Ok(c) = Composite::parse(type_path) {
return Ok(Token::Composite(c));
}
Err(Error::TokenInitFailed(format!(
"Couldn't initialize a Token from type path `{}`",
type_path,
)))
}
pub fn type_name(&self) -> String {
match self {
Token::CoreBasic(t) => t.type_name(),
Token::Array(_) => "array".to_string(),
Token::Tuple(_) => "tuple".to_string(),
Token::Composite(t) => t.type_name(),
Token::GenericArg(_) => "generic_arg".to_string(),
Token::Function(_) => "function".to_string(),
}
}
pub fn type_path(&self) -> String {
match self {
Token::CoreBasic(t) => t.type_path.to_string(),
Token::Array(t) => t.type_path.to_string(),
Token::Tuple(t) => t.type_path.to_string(),
Token::Composite(t) => t.type_path_no_generic(),
Token::GenericArg(_) => "generic".to_string(),
Token::Function(t) => t.name.clone(),
}
}
// TODO: we may remove these two functions...! And change types somewhere..
pub fn to_composite(&self) -> CainomeResult<&Composite> {
match self {
Token::Composite(t) => Ok(t),
_ => Err(Error::ConversionFailed(format!(
"Can't convert token into composite, got {:?}",
self
))),
}
}
pub fn to_function(&self) -> CainomeResult<&Function> {
match self {
Token::Function(t) => Ok(t),
_ => Err(Error::ConversionFailed(format!(
"Can't convert token into function, got {:?}",
self
))),
}
}
pub fn resolve_generic(&self, generic_name: &str, generic_type_path: &str) -> Self {
match self {
Token::CoreBasic(t) => {
if t.type_path == generic_type_path {
Token::GenericArg(generic_name.to_string())
} else {
self.clone()
}
}
Token::Array(t) => t.resolve_generic(generic_name, generic_type_path),
Token::Tuple(t) => t.resolve_generic(generic_name, generic_type_path),
Token::Composite(t) => t.resolve_generic(generic_name, generic_type_path),
Token::GenericArg(_) => self.clone(),
Token::Function(_) => self.clone(),
}
}
pub fn apply_alias(&mut self, type_path: &str, alias: &str) {
match self {
Token::Array(t) => t.apply_alias(type_path, alias),
Token::Tuple(t) => t.apply_alias(type_path, alias),
Token::Composite(t) => t.apply_alias(type_path, alias),
Token::Function(t) => t.apply_alias(type_path, alias),
_ => (),
}
}
/// Recursively hydrates nested tokens
///
/// Once abi is parsed, a flat list of tokens defined in cairo code is generated from parsed
/// json abi string.
/// Then token list are filtered to only keep single copy of each token.
/// Some tokens can have nested tokens that may not have inners defined inside thus leading to
/// confusion while using tokens. i.e Enums does not have inner variants defined.
///
/// # Arguments
///
/// * `token` - The token to hydrate.
/// * `filtered` - A map of type path to token that have already been hydrated.
///
pub fn hydrate(token: Self, filtered: &HashMap<String, Token>) -> Self {
match token {
Token::CoreBasic(_) | Token::GenericArg(_) => token,
Token::Array(arr) => Token::Array(Array {
inner: Box::new(Self::hydrate(*arr.inner, filtered)),
type_path: arr.type_path,
is_legacy: arr.is_legacy,
}),
Token::Tuple(tup) => Token::Tuple(Tuple {
inners: tup
.inners
.into_iter()
.map(|inner| Self::hydrate(inner, filtered))
.collect(),
type_path: tup.type_path,
}),
Token::Composite(comp) => {
if comp.r#type == CompositeType::Unknown && !comp.is_builtin() {
if let Some(hydrated) = filtered.get(&comp.type_path) {
return hydrated.clone();
} else {
panic!("Composite {} not found in filtered tokens", comp.type_path);
}
}
Token::Composite(Composite {
type_path: comp.type_path,
inners: comp
.inners
.into_iter()
.map(|i| CompositeInner {
index: i.index,
name: i.name,
kind: i.kind,
token: Self::hydrate(i.token, filtered),
})
.collect(),
generic_args: comp.generic_args,
r#type: comp.r#type,
is_event: comp.is_event,
alias: comp.alias,
})
}
Token::Function(func) => Token::Function(Function {
name: func.name,
inputs: func
.inputs
.into_iter()
.map(|(name, token)| (name, Self::hydrate(token, filtered)))
.collect(),
outputs: func
.outputs
.into_iter()
.map(|token| Self::hydrate(token, filtered))
.collect(),
named_outputs: func
.named_outputs
.into_iter()
.map(|(name, token)| (name, Self::hydrate(token, filtered)))
.collect(),
state_mutability: func.state_mutability,
}),
}
}
}