/ console / program / src / data / future / 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 Future<N> {
 22      /// Parses a string into a future value.
 23      #[inline]
 24      fn parse(string: &str) -> ParserResult<'_, Self> {
 25          // Parse the future from the string.
 26          Self::parse_internal(string, 0)
 27      }
 28  }
 29  
 30  impl<N: Network> Future<N> {
 31      /// Parses an array of future arguments: `[arg_0, ..., arg_1]`, while tracking the depth of the data.
 32      fn parse_arguments(string: &str, depth: usize) -> ParserResult<'_, Vec<Argument<N>>> {
 33          // Parse the whitespace and comments from the string.
 34          let (string, _) = Sanitizer::parse(string)?;
 35          // Parse the "[" from the string.
 36          let (string, _) = tag("[")(string)?;
 37          // Parse the whitespace from the string.
 38          let (string, _) = Sanitizer::parse(string)?;
 39          // Parse the members.
 40          let (string, arguments) = separated_list0(
 41              pair(pair(Sanitizer::parse_whitespaces, tag(",")), Sanitizer::parse),
 42              alt((
 43                  map(|input| Self::parse_internal(input, depth + 1), Argument::Future),
 44                  map(Plaintext::parse, Argument::Plaintext),
 45              )),
 46          )(string)?;
 47          // Parse the whitespace and comments from the string.
 48          let (string, _) = Sanitizer::parse(string)?;
 49          // Parse the ']' from the string.
 50          let (string, _) = tag("]")(string)?;
 51          // Output the plaintext.
 52          Ok((string, arguments))
 53      }
 54  
 55      /// Parses a string into a future value, while tracking the depth of the data.
 56      #[inline]
 57      fn parse_internal(string: &str, depth: usize) -> ParserResult<'_, Self> {
 58          // Ensure that the depth is within the maximum limit.
 59          // Note: `N::MAX_DATA_DEPTH` is an upper bound on the number of nested futures.
 60          //  The true maximum is defined by `Transaction::<N>::MAX_TRANSITIONS`, however, that object is not accessible in this crate.
 61          //  In practice, `MAX_DATA_DEPTH` is 32, while `MAX_TRANSITIONS` is 31.
 62          if depth > N::MAX_DATA_DEPTH {
 63              return map_res(take(0usize), |_| {
 64                  Err(error(format!("Found a future that exceeds maximum data depth ({})", N::MAX_DATA_DEPTH)))
 65              })(string);
 66          }
 67          // Parse the whitespace and comments from the string.
 68          let (string, _) = Sanitizer::parse(string)?;
 69          // Parse the "{" from the string.
 70          let (string, _) = tag("{")(string)?;
 71  
 72          // Parse the whitespace and comments from the string.
 73          let (string, _) = Sanitizer::parse(string)?;
 74          // Parse the "program_id" from the string.
 75          let (string, _) = tag("program_id")(string)?;
 76          // Parse the whitespace from the string.
 77          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 78          // Parse the ":" from the string.
 79          let (string, _) = tag(":")(string)?;
 80          // Parse the whitespace from the string.
 81          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 82          // Parse the program ID from the string.
 83          let (string, program_id) = ProgramID::parse(string)?;
 84          // Parse the whitespace from the string.
 85          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 86          // Parse the "," from the string.
 87          let (string, _) = tag(",")(string)?;
 88  
 89          // Parse the whitespace and comments from the string.
 90          let (string, _) = Sanitizer::parse(string)?;
 91          // Parse the "function_name" from the string.
 92          let (string, _) = tag("function_name")(string)?;
 93          // Parse the whitespace from the string.
 94          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 95          // Parse the ":" from the string.
 96          let (string, _) = tag(":")(string)?;
 97          // Parse the whitespace from the string.
 98          let (string, _) = Sanitizer::parse_whitespaces(string)?;
 99          // Parse the function name from the string.
100          let (string, function_name) = Identifier::parse(string)?;
101          // Parse the whitespace from the string.
102          let (string, _) = Sanitizer::parse_whitespaces(string)?;
103          // Parse the "," from the string.
104          let (string, _) = tag(",")(string)?;
105  
106          // Parse the whitespace and comments from the string.
107          let (string, _) = Sanitizer::parse(string)?;
108          // Parse the "arguments" from the string.
109          let (string, _) = tag("arguments")(string)?;
110          // Parse the whitespace from the string.
111          let (string, _) = Sanitizer::parse_whitespaces(string)?;
112          // Parse the ":" from the string.
113          let (string, _) = tag(":")(string)?;
114          // Parse the whitespace from the string.
115          let (string, _) = Sanitizer::parse_whitespaces(string)?;
116          // Parse the arguments from the string.
117          let (string, arguments) = Self::parse_arguments(string, depth)?;
118  
119          // Parse the whitespace and comments from the string.
120          let (string, _) = Sanitizer::parse(string)?;
121          // Parse the "}" from the string.
122          let (string, _) = tag("}")(string)?;
123  
124          Ok((string, Self::new(program_id, function_name, arguments)))
125      }
126  }
127  
128  impl<N: Network> FromStr for Future<N> {
129      type Err = Error;
130  
131      /// Returns a future from a string literal.
132      fn from_str(string: &str) -> Result<Self> {
133          match Self::parse(string) {
134              Ok((remainder, object)) => {
135                  // Ensure the remainder is empty.
136                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
137                  // Return the object.
138                  Ok(object)
139              }
140              Err(error) => bail!("Failed to parse string. {error}"),
141          }
142      }
143  }
144  
145  impl<N: Network> Debug for Future<N> {
146      /// Prints the future as a string.
147      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
148          Display::fmt(self, f)
149      }
150  }
151  
152  impl<N: Network> Display for Future<N> {
153      /// Prints the future as a string.
154      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
155          self.fmt_internal(f, 0)
156      }
157  }
158  
159  impl<N: Network> Future<N> {
160      /// Prints the future with the given indentation depth.
161      fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result {
162          /// The number of spaces to indent.
163          const INDENT: usize = 2;
164  
165          // Print the opening brace.
166          write!(f, "{{")?;
167  
168          // Print the program ID.
169          write!(
170              f,
171              "\n{:indent$}program_id: {program_id},",
172              "",
173              indent = (depth + 1) * INDENT,
174              program_id = self.program_id()
175          )?;
176          // Print the function name.
177          write!(
178              f,
179              "\n{:indent$}function_name: {function_name},",
180              "",
181              indent = (depth + 1) * INDENT,
182              function_name = self.function_name()
183          )?;
184          // Print the arguments.
185          // If the arguments are empty, print an empty array.
186          if self.arguments.is_empty() {
187              write!(f, "\n{:indent$}arguments: []", "", indent = (depth + 1) * INDENT)?;
188          } else {
189              write!(f, "\n{:indent$}arguments: [", "", indent = (depth + 1) * INDENT)?;
190              self.arguments.iter().enumerate().try_for_each(|(i, argument)| {
191                  match argument {
192                      Argument::Plaintext(plaintext) => match i == self.arguments.len() - 1 {
193                          true => {
194                              // Print the last argument without a comma.
195                              write!(
196                                  f,
197                                  "\n{:indent$}{plaintext}",
198                                  "",
199                                  indent = (depth + 2) * INDENT,
200                                  plaintext = plaintext
201                              )
202                          }
203                          // Print the argument with a comma.
204                          false => {
205                              write!(
206                                  f,
207                                  "\n{:indent$}{plaintext},",
208                                  "",
209                                  indent = (depth + 2) * INDENT,
210                                  plaintext = plaintext
211                              )
212                          }
213                      },
214                      Argument::Future(future) => {
215                          // Print a newline.
216                          write!(f, "\n{:indent$}", "", indent = (depth + 2) * INDENT)?;
217                          // Print the argument.
218                          future.fmt_internal(f, depth + 2)?;
219                          // Print the closing brace.
220                          match i == self.arguments.len() - 1 {
221                              // Print the last member without a comma.
222                              true => write!(f, "\n{:indent$}", "", indent = (depth + 1) * INDENT),
223                              // Print the member with a comma.
224                              false => write!(f, ","),
225                          }
226                      }
227                  }
228              })?;
229              // Print the closing bracket.
230              write!(f, "\n{:indent$}]", "", indent = (depth + 1) * INDENT)?;
231          }
232  
233          // Print the closing brace.
234          write!(f, "\n{:indent$}}}", "", indent = depth * INDENT)
235      }
236  }
237  
238  #[cfg(test)]
239  mod tests {
240      use super::*;
241      use alphavm_console_network::MainnetV0;
242  
243      type CurrentNetwork = MainnetV0;
244  
245      #[test]
246      fn test_parse_future() -> Result<()> {
247          // No argument case.
248          let expected = r"{
249    program_id: credits.alpha,
250    function_name: transfer,
251    arguments: []
252  }";
253          let (remainder, candidate) =
254              Future::<CurrentNetwork>::parse("{ program_id: credits.alpha, function_name: transfer, arguments: [] }")?;
255          assert!(remainder.is_empty());
256          assert_eq!(expected, candidate.to_string());
257          assert_eq!("", remainder);
258  
259          // Literal arguments.
260          let expected = r"{
261    program_id: credits.alpha,
262    function_name: transfer_public_to_private,
263    arguments: [
264      ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w,
265      100000000u64
266    ]
267  }";
268          let (remainder, candidate) = Future::<CurrentNetwork>::parse(
269              "{ program_id: credits.alpha, function_name: transfer_public_to_private, arguments: [ ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w, 100000000u64 ] }",
270          )?;
271          assert!(remainder.is_empty());
272          assert_eq!(expected, candidate.to_string());
273          assert_eq!("", remainder);
274  
275          Ok(())
276      }
277  
278      #[test]
279      fn test_deeply_nested_future() {
280          // A helper function to iteratively create a deeply nested future.
281          fn create_nested_future(depth: usize) -> String {
282              // Define the base case.
283              let root = r"{
284                  program_id: foo.alpha,
285                  function_name: bar,
286                  arguments: []
287              }";
288              // Define the prefix and suffix for the nested future.
289              let prefix = r"{
290                  program_id: foo.alpha,
291                  function_name: bar,
292                  arguments: ["
293                  .repeat(depth);
294              let suffix = r"]}".repeat(depth);
295              // Concatenate the prefix, root, and suffix to create the nested future.
296              format!("{prefix}{root}{suffix}")
297          }
298  
299          // A helper function to test the parsing of a deeply nested future.
300          fn run_test(depth: usize, expected_error: bool) {
301              // Create the nested future string.
302              let nested_future_string = create_nested_future(depth);
303              // Parse the nested future.
304              let result = Future::<CurrentNetwork>::parse(&nested_future_string);
305              // Check if the result is an error.
306              match expected_error {
307                  true => {
308                      assert!(result.is_err());
309                      return;
310                  }
311                  false => assert!(result.is_ok()),
312              };
313              // Unwrap the result.
314              let (remainder, candidate) = result.unwrap();
315              // Ensure the remainder is empty.
316              assert!(
317                  remainder.is_empty(),
318                  "Failed to parse deeply nested future. Found invalid character in: \"{remainder}\""
319              );
320              // Strip the expected string of whitespace.
321              let expected = nested_future_string.replace("\n", "").replace(" ", "").replace("\t", "");
322              // Strip the candidate string of whitespace.
323              let candidate_str = candidate.to_string().replace("\n", "").replace(" ", "").replace("\t", "");
324              // Ensure the expected and candidate strings are equal.
325              assert_eq!(expected, candidate_str, "Expected: {expected}, Candidate: {candidate_str}");
326          }
327  
328          // Initialize a set of depths to test.
329          let mut depths = (0usize..100).collect_vec();
330          depths.extend((100..1000).step_by(100));
331          depths.extend((1000..10000).step_by(1000));
332          depths.extend((10000..100000).step_by(10000));
333  
334          // For each depth, test the parsing of a deeply nested future.
335          for depth in depths {
336              run_test(depth, depth > CurrentNetwork::MAX_DATA_DEPTH);
337          }
338      }
339  }