parse.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphavm library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 use super::*; 20 21 impl<N: Network> Parser for Entry<N, Plaintext<N>> { 22 /// Parses a string into the entry. 23 #[inline] 24 fn parse(string: &str) -> ParserResult<'_, Self> { 25 /// A helper enum encoding the visibility. 26 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 27 enum Mode { 28 Constant, 29 Public, 30 Private, 31 } 32 33 /// Parses a sanitized pair: `identifier: entry`, while tracking the depth of the data. 34 fn parse_pair<N: Network>(string: &str, depth: usize) -> ParserResult<'_, (Identifier<N>, Plaintext<N>, Mode)> { 35 // Parse the whitespace and comments from the string. 36 let (string, _) = Sanitizer::parse(string)?; 37 // Parse the identifier from the string. 38 let (string, identifier) = Identifier::parse(string)?; 39 // Parse the whitespace from the string. 40 let (string, _) = Sanitizer::parse_whitespaces(string)?; 41 // Parse the ":" from the string. 42 let (string, _) = tag(":")(string)?; 43 // Parse the whitespace from the string. 44 let (string, _) = Sanitizer::parse_whitespaces(string)?; 45 // Parse the plaintext and visibility from the string. 46 let (string, (plaintext, mode)) = alt(( 47 // Parse a literal. 48 |input| parse_literal(input, depth), 49 // Parse a struct. 50 |input| parse_struct(input, depth), 51 // Parse an array. 52 |input| parse_array(input, depth), 53 ))(string)?; 54 // Parse the whitespace from the string. 55 let (string, _) = Sanitizer::parse_whitespaces(string)?; 56 // Return the identifier, plaintext, and visibility. 57 Ok((string, (identifier, plaintext, mode))) 58 } 59 60 /// Parses an entry as a literal: `literal.visibility`, while tracking the depth of the data. 61 fn parse_literal<N: Network>(string: &str, depth: usize) -> ParserResult<'_, (Plaintext<N>, Mode)> { 62 // Ensure that the depth is within the maximum limit. 63 if depth > N::MAX_DATA_DEPTH { 64 return map_res(take(0usize), |_| { 65 Err(error(format!("Found an entry future that exceeds maximum data depth ({})", N::MAX_DATA_DEPTH))) 66 })(string); 67 } 68 alt(( 69 map(pair(Literal::parse, tag(".constant")), |(literal, _)| (Plaintext::from(literal), Mode::Constant)), 70 map(pair(Literal::parse, tag(".public")), |(literal, _)| (Plaintext::from(literal), Mode::Public)), 71 map(pair(Literal::parse, tag(".private")), |(literal, _)| (Plaintext::from(literal), Mode::Private)), 72 ))(string) 73 } 74 75 /// Parses an entry as a struct: `{ identifier_0: plaintext_0.visibility, ..., identifier_n: plaintext_n.visibility }`, while tracking the depth of the data. 76 /// Observe the `visibility` is the same for all members of the plaintext value. 77 fn parse_struct<N: Network>(string: &str, depth: usize) -> ParserResult<'_, (Plaintext<N>, Mode)> { 78 // Ensure that the depth is within the maximum limit. 79 if depth > N::MAX_DATA_DEPTH { 80 return map_res(take(0usize), |_| { 81 Err(error(format!("Found an entry that exceeds maximum data depth ({})", N::MAX_DATA_DEPTH))) 82 })(string); 83 } 84 // Parse the whitespace and comments from the string. 85 let (string, _) = Sanitizer::parse(string)?; 86 // Parse the "{" from the string. 87 let (string, _) = tag("{")(string)?; 88 // Parse the whitespace from the string. 89 let (string, _) = Sanitizer::parse_whitespaces(string)?; 90 // Parse the members. 91 let (string, (members, mode)) = 92 map_res(separated_list1(tag(","), |input| parse_pair(input, depth + 1)), |members: Vec<_>| { 93 // Ensure the members has no duplicate names. 94 if has_duplicates(members.iter().map(|(name, ..)| name)) { 95 return Err(error("Duplicate member in struct")); 96 } 97 // Ensure the members all have the same visibility. 98 let mode = members.iter().map(|(_, _, mode)| mode).dedup().collect::<Vec<_>>(); 99 let mode = match mode.len() == 1 { 100 true => *mode[0], 101 false => return Err(error("Members of struct in entry have different visibilities")), 102 }; 103 // Ensure the number of structs is within the maximum limit. 104 match members.len() <= N::MAX_STRUCT_ENTRIES { 105 // Return the members and the visibility. 106 true => Ok((members.into_iter().map(|(i, p, _)| (i, p)).collect::<Vec<_>>(), mode)), 107 false => Err(error(format!("Found a struct that exceeds size ({})", members.len()))), 108 } 109 })(string)?; 110 // Parse the whitespace and comments from the string. 111 let (string, _) = Sanitizer::parse(string)?; 112 // Parse the '}' from the string. 113 let (string, _) = tag("}")(string)?; 114 // Output the plaintext and visibility. 115 Ok((string, (Plaintext::Struct(IndexMap::from_iter(members), Default::default()), mode))) 116 } 117 118 /// Parses an entry as an array: `[plaintext_0.visibility, ..., plaintext_n.visibility]`, while tracking the depth of the data. 119 /// Observe the `visibility` is the same for all members of the plaintext value. 120 fn parse_array<N: Network>(string: &str, depth: usize) -> ParserResult<'_, (Plaintext<N>, Mode)> { 121 // Ensure that the depth is within the maximum limit. 122 if depth > N::MAX_DATA_DEPTH { 123 return map_res(take(0usize), |_| { 124 Err(error(format!("Found an entry future that exceeds maximum data depth ({})", N::MAX_DATA_DEPTH))) 125 })(string); 126 } 127 // Parse the whitespace and comments from the string. 128 let (string, _) = Sanitizer::parse(string)?; 129 // Parse the "[" from the string. 130 let (string, _) = tag("[")(string)?; 131 // Parse the whitespace from the string. 132 let (string, _) = Sanitizer::parse_whitespaces(string)?; 133 // Parse the members. 134 let (string, (elements, mode)) = map_res( 135 separated_list1( 136 pair(Sanitizer::parse_whitespaces, pair(tag(","), Sanitizer::parse_whitespaces)), 137 alt(( 138 |input| parse_literal(input, depth + 1), 139 |input| parse_struct(input, depth + 1), 140 |input| parse_array(input, depth + 1), 141 )), 142 ), 143 |members: Vec<(Plaintext<N>, Mode)>| { 144 // Ensure the members all have the same visibility. 145 let mode = members.iter().map(|(_, mode)| mode).dedup().collect::<Vec<_>>(); 146 let mode = match mode.len() == 1 { 147 true => *mode[0], 148 false => return Err(error("Members of an array have different visibilities")), 149 }; 150 // Ensure the number of array elements is within the maximum limit. 151 match members.len() <= N::MAX_ARRAY_ELEMENTS { 152 // Return the members and the visibility. 153 true => Ok((members.into_iter().map(|(p, _)| p).collect::<Vec<_>>(), mode)), 154 false => Err(error(format!("Found an array that exceeds size ({})", members.len()))), 155 } 156 }, 157 )(string)?; 158 // Parse the whitespace and comments from the string. 159 let (string, _) = Sanitizer::parse(string)?; 160 // Parse the ']' from the string. 161 let (string, _) = tag("]")(string)?; 162 // Output the plaintext and visibility. 163 Ok((string, (Plaintext::Array(elements, Default::default()), mode))) 164 } 165 166 // Parse the whitespace from the string. 167 let (string, _) = Sanitizer::parse_whitespaces(string)?; 168 // Parse to determine the entry (order matters). 169 let (string, (plaintext, mode)) = alt(( 170 // Parse a literal. 171 |input| parse_literal(input, 0), 172 // Parse a struct. 173 |input| parse_struct(input, 0), 174 // Parse an array. 175 |input| parse_array(input, 0), 176 ))(string)?; 177 178 // Return the entry. 179 match mode { 180 Mode::Constant => Ok((string, Entry::Constant(plaintext))), 181 Mode::Public => Ok((string, Entry::Public(plaintext))), 182 Mode::Private => Ok((string, Entry::Private(plaintext))), 183 } 184 } 185 } 186 187 impl<N: Network> FromStr for Entry<N, Plaintext<N>> { 188 type Err = Error; 189 190 /// Returns the entry from a string literal. 191 fn from_str(string: &str) -> Result<Self> { 192 match Self::parse(string) { 193 Ok((remainder, object)) => { 194 // Ensure the remainder is empty. 195 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 196 // Return the object. 197 Ok(object) 198 } 199 Err(error) => bail!("Failed to parse string. {error}"), 200 } 201 } 202 } 203 204 impl<N: Network> Debug for Entry<N, Plaintext<N>> { 205 /// Prints the entry as a string. 206 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 207 Display::fmt(self, f) 208 } 209 } 210 211 impl<N: Network> Display for Entry<N, Plaintext<N>> { 212 /// Prints the entry as a string. 213 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 214 self.fmt_internal(f, 0) 215 } 216 } 217 218 impl<N: Network> Entry<N, Plaintext<N>> { 219 /// Prints the entry with the given indentation depth. 220 pub(in crate::data::record) fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result { 221 /// The number of spaces to indent. 222 const INDENT: usize = 2; 223 224 let (plaintext, visibility) = match self { 225 Self::Constant(constant) => (constant, "constant"), 226 Self::Public(public) => (public, "public"), 227 Self::Private(private) => (private, "private"), 228 }; 229 230 match plaintext { 231 // Prints the literal, i.e. 10field.public 232 Plaintext::Literal(literal, ..) => { 233 write!(f, "{:indent$}{literal}.{visibility}", "", indent = depth * INDENT) 234 } 235 // Prints the struct, i.e. { first: 10i64.private, second: 198u64.private } 236 Plaintext::Struct(struct_, ..) => { 237 // Print the opening brace. 238 write!(f, "{{")?; 239 // Print the members. 240 struct_.iter().enumerate().try_for_each(|(i, (name, plaintext))| { 241 match plaintext { 242 #[rustfmt::skip] 243 Plaintext::Literal(literal, ..) => match i == struct_.len() - 1 { 244 true => { 245 // Print the last member without a comma. 246 write!(f, "\n{:indent$}{name}: {literal}.{visibility}", "", indent = (depth + 1) * INDENT)?; 247 // Print the closing brace. 248 write!(f, "\n{:indent$}}}", "", indent = depth * INDENT) 249 } 250 // Print the member with a comma. 251 false => write!(f, "\n{:indent$}{name}: {literal}.{visibility},", "", indent = (depth + 1) * INDENT), 252 }, 253 Plaintext::Struct(..) | Plaintext::Array(..) => { 254 // Print the member name. 255 write!(f, "\n{:indent$}{name}: ", "", indent = (depth + 1) * INDENT)?; 256 // Print the member. 257 match self { 258 Self::Constant(..) => Self::Constant(plaintext.clone()).fmt_internal(f, depth + 1)?, 259 Self::Public(..) => Self::Public(plaintext.clone()).fmt_internal(f, depth + 1)?, 260 Self::Private(..) => Self::Private(plaintext.clone()).fmt_internal(f, depth + 1)?, 261 } 262 // Print the closing brace. 263 match i == struct_.len() - 1 { 264 // If this inner struct is the last member of the outer struct, print the closing brace of the outer struct. 265 true => write!(f, "\n{:indent$}}}", "", indent = depth * INDENT), 266 // Otherwise, print a comma after the inner struct, because the outer struct has more members after this one. 267 false => write!(f, ","), 268 } 269 }, 270 } 271 }) 272 } 273 // Prints the array, i.e. [ 10u64.public, 198u64.private ] 274 Plaintext::Array(array, ..) => { 275 // Print the opening bracket. 276 write!(f, "[")?; 277 // Print the members. 278 array.iter().enumerate().try_for_each(|(i, plaintext)| { 279 match plaintext { 280 #[rustfmt::skip] 281 Plaintext::Literal(literal, ..) => match i == array.len() - 1 { 282 true => { 283 // Print the last member without a comma. 284 write!(f, "\n{:indent$}{literal}.{visibility}", "", indent = (depth + 1) * INDENT)?; 285 // Print the closing brace. 286 write!(f, "\n{:indent$}]", "", indent = depth * INDENT) 287 } 288 // Print the member with a comma. 289 false => write!(f, "\n{:indent$}{literal}.{visibility},", "", indent = (depth + 1) * INDENT), 290 }, 291 Plaintext::Struct(..) | Plaintext::Array(..) => { 292 // Print a new line. 293 write!(f, "\n{:indent$}", "", indent = (depth + 1) * INDENT)?; 294 // Print the member. 295 match self { 296 Self::Constant(..) => Self::Constant(plaintext.clone()).fmt_internal(f, depth + 1)?, 297 Self::Public(..) => Self::Public(plaintext.clone()).fmt_internal(f, depth + 1)?, 298 Self::Private(..) => Self::Private(plaintext.clone()).fmt_internal(f, depth + 1)?, 299 } 300 // Print the closing brace. 301 match i == array.len() - 1 { 302 // If this inner struct is the last member of the outer struct, print the closing bracket of the outer vector. 303 true => write!(f, "\n{:indent$}]", "", indent = depth * INDENT), 304 // Otherwise, print a comma after the inner struct, because the outer vector has more members after this one. 305 false => write!(f, ","), 306 } 307 }, 308 } 309 }) 310 } 311 } 312 } 313 } 314 315 #[cfg(test)] 316 mod tests { 317 use super::*; 318 use alphavm_console_network::MainnetV0; 319 320 type CurrentNetwork = MainnetV0; 321 322 #[test] 323 fn test_parse() -> Result<()> { 324 // Sanity check. 325 let expected = r"{ 326 foo: 5u8.private 327 }"; 328 let (remainder, candidate) = Entry::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse("{ foo: 5u8.private }")?; 329 assert_eq!(expected, candidate.to_string()); 330 assert_eq!("", remainder); 331 332 let expected = r"{ 333 foo: 5u8.public, 334 bar: { 335 baz: 10field.public, 336 qux: { 337 quux: { 338 corge: { 339 grault: { 340 garply: { 341 waldo: { 342 fred: { 343 plugh: { 344 xyzzy: { 345 thud: true.public 346 } 347 } 348 } 349 } 350 } 351 } 352 } 353 } 354 } 355 } 356 }"; 357 let (remainder, candidate) = Entry::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse( 358 "{ foo: 5u8.public, bar: { baz: 10field.public, qux: {quux:{corge :{grault: {garply:{waldo:{fred:{plugh:{xyzzy: { thud: true.public}} }}} }}}}}}", 359 )?; 360 println!("\nExpected: {expected}\n\nFound: {candidate}\n"); 361 assert_eq!(expected, candidate.to_string()); 362 assert_eq!("", remainder); 363 364 // Test an array of literals. 365 let expected = r"[ 366 5u8.private, 367 10u8.private, 368 15u8.private 369 ]"; 370 let (remainder, candidate) = 371 Entry::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse("[ 5u8.private, 10u8.private, 15u8.private ]")?; 372 assert_eq!(expected, candidate.to_string()); 373 assert_eq!("", remainder); 374 375 // Test an array of structs. 376 let expected = r"[ 377 { 378 foo: 5u8.public 379 }, 380 { 381 bar: 10u8.public 382 }, 383 { 384 baz: 15u8.public 385 } 386 ]"; 387 let (remainder, candidate) = Entry::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse( 388 "[ { foo: 5u8.public }, { bar: 10u8.public }, { baz: 15u8.public } ]", 389 )?; 390 assert_eq!(expected, candidate.to_string()); 391 assert_eq!("", remainder); 392 393 // Test a struct with arrays. 394 let expected = r"{ 395 foo: [ 396 5u8.public, 397 10u8.public, 398 15u8.public 399 ], 400 bar: [ 401 { 402 foo: 5u8.public 403 }, 404 { 405 bar: 10u8.public 406 }, 407 { 408 baz: 15u8.public 409 } 410 ] 411 }"; 412 let (remainder, candidate) = Entry::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse( 413 "{ foo: [ 5u8.public, 10u8.public, 15u8.public ], bar: [ { foo: 5u8.public }, { bar: 10u8.public }, { baz: 15u8.public } ] }", 414 )?; 415 assert_eq!(expected, candidate.to_string()); 416 assert_eq!("", remainder); 417 418 Ok(()) 419 } 420 421 // A helper function to get the depth of the plaintext. 422 fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize { 423 match plaintext { 424 Plaintext::Literal(_, _) => 0, 425 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1, 426 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1, 427 } 428 } 429 430 #[test] 431 fn test_deeply_nested_entry() { 432 // Creates a string representation of a nested array Entry with the given depth and root. 433 fn create_nested_array(depth: usize, root: impl Display) -> String { 434 // Define the prefix and suffix based on the depth. 435 let prefix = if depth == 0 { "".to_string() } else { "[".repeat(depth) }; 436 let suffix = if depth == 0 { "".to_string() } else { "]".repeat(depth) }; 437 // Format the string with the prefix, root, and suffix. 438 format!("{prefix}{root}{suffix}") 439 } 440 441 // Creates a string representation of a nested struct Entry with the given depth and root. 442 fn create_nested_struct(depth: usize, root: impl Display) -> String { 443 // Define the prefix and suffix based on the depth. 444 let prefix = if depth == 0 { "".to_string() } else { "{inner:".repeat(depth) }; 445 let suffix = if depth == 0 { "".to_string() } else { "}".repeat(depth) }; 446 // Format the string with the prefix, root, and suffix. 447 format!("{prefix}{root}{suffix}") 448 } 449 450 // Creates a string representation of a nested Entry with alternating structs and arrays with the given depth and root. 451 fn create_alternated_nested(depth: usize, root: impl Display) -> String { 452 let prefix = (0..depth).map(|i| if i % 2 == 0 { "[" } else { "{inner:" }).collect::<String>(); 453 let suffix = (0..depth).map(|i| if i % 2 == 0 { "]" } else { "}" }).rev().collect::<String>(); 454 format!("{prefix}{root}{suffix}") 455 } 456 457 // A helper function to run the test. 458 fn run_test(expected_depth: usize, input: String, expected_error: bool) { 459 println!("Testing input: {input} with expected error: {expected_error}"); 460 // Parse the input string. 461 let result = Entry::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(&input); 462 // Check if the result is an error. 463 match expected_error { 464 true => { 465 assert!(result.is_err()); 466 return; 467 } 468 false => assert!(result.is_ok()), 469 }; 470 // Unwrap the result. 471 let (remainder, candidate) = result.unwrap(); 472 // Check if the remainder is empty. 473 assert!(remainder.is_empty()); 474 // Check if the candidate is equal to the input, with whitespace removed. 475 assert_eq!(input, candidate.to_string().replace("\n", "").replace(" ", "")); 476 // Check if the candidate is equal to the expected depth. 477 match candidate { 478 Entry::Constant(plaintext) => { 479 assert_eq!(get_depth(&plaintext), expected_depth); 480 } 481 Entry::Public(plaintext) => { 482 assert_eq!(get_depth(&plaintext), expected_depth); 483 } 484 Entry::Private(plaintext) => { 485 assert_eq!(get_depth(&plaintext), expected_depth); 486 } 487 } 488 } 489 490 // Initialize a sequence of depths to check. 491 let mut depths = (0usize..100).collect_vec(); 492 depths.extend((100..1000).step_by(100)); 493 depths.extend((1000..10000).step_by(1000)); 494 depths.extend((10000..100000).step_by(10000)); 495 496 // Test deeply nested arrays with different literal types. 497 for i in depths.iter().copied() { 498 run_test(i, create_nested_array(i, "false.constant"), i > CurrentNetwork::MAX_DATA_DEPTH); 499 run_test(i, create_nested_array(i, "1u8.public"), i > CurrentNetwork::MAX_DATA_DEPTH); 500 run_test(i, create_nested_array(i, "0u128.private"), i > CurrentNetwork::MAX_DATA_DEPTH); 501 run_test(i, create_nested_array(i, "10field.constant"), i > CurrentNetwork::MAX_DATA_DEPTH); 502 } 503 504 // Test deeply nested structs with different literal types. 505 for i in depths.iter().copied() { 506 run_test(i, create_nested_struct(i, "false.public"), i > CurrentNetwork::MAX_DATA_DEPTH); 507 run_test(i, create_nested_struct(i, "1u8.private"), i > CurrentNetwork::MAX_DATA_DEPTH); 508 run_test(i, create_nested_struct(i, "0u128.constant"), i > CurrentNetwork::MAX_DATA_DEPTH); 509 run_test(i, create_nested_struct(i, "10field.public"), i > CurrentNetwork::MAX_DATA_DEPTH); 510 } 511 512 // Test alternating nested arrays and structs. 513 for i in depths.iter().copied() { 514 run_test(i, create_alternated_nested(i, "false.private"), i > CurrentNetwork::MAX_DATA_DEPTH); 515 run_test(i, create_alternated_nested(i, "1u8.constant"), i > CurrentNetwork::MAX_DATA_DEPTH); 516 run_test(i, create_alternated_nested(i, "0u128.public"), i > CurrentNetwork::MAX_DATA_DEPTH); 517 run_test(i, create_alternated_nested(i, "10field.private"), i > CurrentNetwork::MAX_DATA_DEPTH); 518 } 519 } 520 }