/ console / program / src / data / record / entry / parse.rs
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  }