aleo_struct_parser/
lib.rs1use serde_json::Map;
2
3mod number;
4mod serde;
5
6pub use serde::Address;
7pub use serde::from_str;
8
9pub fn to_json_value(input: &str) -> serde_json::Value {
10 parse_struct(input)
11}
12
13struct Cursor<'a> {
14 ref_str: &'a str,
15 start: usize,
16 end: usize,
17}
18
19impl<'a> Cursor<'a> {
20 fn new(ref_str: &str) -> Cursor {
21 Cursor {
22 ref_str,
23 start: 0,
24 end: 0,
25 }
26 }
27
28 fn push(&mut self, idx: usize) {
29 if self.start == 0 {
30 self.start = idx;
31 }
32 self.end = idx + 1;
33 }
34
35 fn clear(&mut self) {
36 self.start = 0;
37 self.end = 0;
38 }
39
40 fn is_empty(&self) -> bool {
41 self.end == 0
42 }
43
44 fn get_str(&self) -> &'a str {
45 &self.ref_str[self.start..self.end]
46 }
47}
48
49fn is_array(input: &str) -> bool {
50 for char in input.chars() {
51 if char == ' ' || char == '\n' || char == '\r' {
52 continue;
53 }
54 if char == '[' {
55 return true;
56 }
57 return false;
58 }
59 false
60}
61
62fn is_field(input: &str) -> bool {
63 for char in input.chars() {
64 if char == ' ' || char == '\n' || char == '\r' {
65 continue;
66 }
67 if char == '[' || char == '{' {
68 return false;
69 }
70 return true;
71 }
72 false
73}
74
75pub(crate) fn parse_struct(input: &str) -> serde_json::Value {
77 if is_array(input) {
78 return serde_json::Value::Array(parse_array(input));
79 }
80
81 if is_field(input) {
82 return serde_json::Value::String(input.to_owned());
83 }
84
85 let mut self_map: Map<String, serde_json::Value> = Map::new();
86 let mut depth = 0;
87 let mut current_key = Cursor::new(input);
88 let mut current_child = Cursor::new(input);
89 let mut current_child_stack = 0;
90 let mut is_key = true;
91
92 for (idx, token) in input.char_indices() {
93 match token {
94 '{' => {
95 depth += 1;
96 if depth != 1 {
97 current_child.push(idx);
98 current_child_stack += 1;
99 }
100 }
101 '}' => {
102 depth -= 1;
103 if depth == 0 {
104 break;
105 } else {
106 current_child.push(idx);
107 current_child_stack -= 1;
108 if current_child_stack == 0 {
109 let current_child_str = current_child.get_str();
110 let current_key_str = current_key.get_str();
111 self_map
112 .insert(current_key_str.to_owned(), parse_struct(current_child_str));
113 current_key.clear();
114 current_child.clear();
115 is_key = true;
116 }
117 }
118 }
119 '[' => {
120 depth += 1;
121 current_child.push(idx);
122 current_child_stack += 1;
123 if depth == 1 {
124 is_key = false;
125 }
126 }
127 ']' => {
128 depth -= 1;
129 current_child.push(idx);
130 current_child_stack -= 1;
131 if current_child_stack == 0 {
132 let current_key_str = current_key.get_str();
133 let current_child_str = current_child.get_str();
134 self_map.insert(
135 current_key_str.to_owned(),
136 serde_json::Value::Array(parse_array(current_child_str)),
137 );
138 current_key.clear();
139 current_child.clear();
140 }
141 }
142 ':' => {
143 if depth == 1 {
144 is_key = false;
145 } else {
146 current_child.push(idx);
147 }
148 }
149 '\n' | ' ' | '\r' => {}
150 ',' => {
151 if depth == 1 {
152 if !current_key.is_empty() {
153 let current_key_str = current_key.get_str();
154 let current_child_str = current_child.get_str();
155 self_map.insert(
156 current_key_str.to_owned(),
157 serde_json::Value::String(current_child_str.to_owned()),
158 );
159 }
160 current_key.clear();
161 current_child.clear();
162 is_key = true;
163 } else {
164 current_child.push(idx);
165 }
166 }
167 _ => {
168 if depth == 1 {
169 if is_key {
170 current_key.push(idx);
171 } else {
172 current_child.push(idx);
173 }
174 } else {
175 current_child.push(idx);
176 }
177 }
178 }
179 }
180
181 if !current_key.is_empty() {
182 self_map.insert(
183 current_key.get_str().to_owned(),
184 serde_json::Value::String(current_child.get_str().to_owned()),
185 );
186 }
187
188 serde_json::Value::Object(self_map)
189}
190
191fn parse_array(input: &str) -> Vec<serde_json::Value> {
192 let mut self_vec: Vec<serde_json::Value> = Vec::new();
193 let mut depth = 0;
194 let mut current_item = Cursor::new(input);
195 let mut current_item_stack = 0;
196
197 let mut current_object: Option<serde_json::Value> = None;
198
199 for (idx, token) in input.char_indices() {
200 match token {
201 '{' => {
202 depth += 1;
203 current_item.push(idx);
204 current_item_stack += 1;
205 }
206 '}' => {
207 depth -= 1;
208 current_item.push(idx);
209 current_item_stack -= 1;
210 if current_item_stack == 0 {
211 current_object = Some(parse_struct(current_item.get_str()));
212 }
213 }
214 '[' => {
215 depth += 1;
216 if depth != 1 {
217 current_item.push(idx);
218 current_item_stack += 1;
219 }
220 }
221 ']' => {
222 depth -= 1;
223 if depth == 0 {
224 if let Some(obj) = current_object.take() {
225 self_vec.push(obj);
226 current_object = None;
227 } else {
228 self_vec.push(serde_json::Value::String(current_item.get_str().to_owned()));
229 current_item.clear();
230 current_item_stack = 0;
231 }
232 } else {
233 current_item.push(idx);
234 current_item_stack -= 1;
235 if current_item_stack == 0 {
236 current_object = Some(serde_json::Value::Array(parse_array(
237 current_item.get_str(),
238 )));
239 }
240 }
241 }
242 ':' => {
243 current_item.push(idx);
244 }
245 '\n' | ' ' | '\r' => {}
246 ',' => {
247 if depth == 1 {
248 if let Some(obj) = current_object.take() {
249 self_vec.push(obj);
250 current_object = None;
251 } else {
252 self_vec.push(serde_json::Value::String(current_item.get_str().to_owned()));
253 current_item.clear();
254 }
255 } else {
256 current_item.push(idx);
257 }
258 }
259 _ => {
260 current_item.push(idx);
261 }
262 }
263 }
264
265 self_vec
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_parse_struct() {
274 let input = r#"
275 {
276 program_id: puzzle_arcade_ticket_v002.aleo,
277 function_name: mint,
278 arguments: [
279 aleo13dn2lyphtrn8mujxcqt4vm2rc567k0s3gnnks985p0hhyvfc9yqqy6rdsl
280 ]
281 }
282 "#;
283 let expect = r#"
284 {
285 "program_id": "puzzle_arcade_ticket_v002.aleo",
286 "function_name": "mint",
287 "arguments": [
288 "aleo13dn2lyphtrn8mujxcqt4vm2rc567k0s3gnnks985p0hhyvfc9yqqy6rdsl"
289 ]
290 }
291 "#;
292 let parsed_struct = parse_struct(input);
293 assert_eq!(
297 expect.trim().replace(' ', ""),
298 serde_json::to_string_pretty(&parsed_struct)
299 .unwrap()
300 .trim()
301 .replace(' ', "")
302 );
303 }
304}