/ console / types / string / src / 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<E: Environment> Parser for StringType<E> {
 22      /// Parses a string into a string type.
 23      #[inline]
 24      fn parse(string: &str) -> ParserResult<'_, Self> {
 25          // Parse the starting and ending quote '"' keyword from the string.
 26          let (string, value) = string_parser::parse_string(string)?;
 27  
 28          Ok((string, StringType::new(&value)))
 29      }
 30  }
 31  
 32  impl<E: Environment> FromStr for StringType<E> {
 33      type Err = Error;
 34  
 35      /// Parses a string into a string type.
 36      #[inline]
 37      fn from_str(string: &str) -> Result<Self> {
 38          match Self::parse(string) {
 39              Ok((remainder, object)) => {
 40                  // Ensure the remainder is empty.
 41                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
 42                  // Return the object.
 43                  Ok(object)
 44              }
 45              Err(error) => bail!("Failed to parse string. {error}"),
 46          }
 47      }
 48  }
 49  
 50  impl<E: Environment> Debug for StringType<E> {
 51      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 52          Display::fmt(self, f)
 53      }
 54  }
 55  
 56  impl<E: Environment> Display for StringType<E> {
 57      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 58          write!(f, "\"{}\"", self.string)
 59      }
 60  }
 61  
 62  #[cfg(test)]
 63  mod tests {
 64      use super::*;
 65      use alphavm_console_network_environment::Console;
 66  
 67      type CurrentEnvironment = Console;
 68  
 69      const ITERATIONS: u32 = 100;
 70  
 71      #[test]
 72      fn test_display() -> Result<()> {
 73          // Ensure type and empty value fails.
 74          assert!(StringType::<CurrentEnvironment>::parse(StringType::<CurrentEnvironment>::type_name()).is_err());
 75          assert!(StringType::<CurrentEnvironment>::parse("").is_err());
 76  
 77          // Ensure empty string succeeds.
 78          assert!(StringType::<CurrentEnvironment>::parse("\"\"").is_ok());
 79  
 80          let rng = &mut TestRng::default();
 81  
 82          for _ in 0..ITERATIONS {
 83              // Sample a random string. Take 1/4th to ensure we fit for all code points.
 84              let expected = rng.next_string(CurrentEnvironment::MAX_STRING_BYTES / 4, false);
 85              let expected_num_bytes = expected.len();
 86              assert!(expected_num_bytes <= CurrentEnvironment::MAX_STRING_BYTES as usize);
 87  
 88              let candidate = StringType::<CurrentEnvironment>::new(&expected);
 89              assert_eq!(format!("\"{expected}\""), format!("{candidate}"));
 90  
 91              let candidate_recovered = StringType::<CurrentEnvironment>::from_str(&format!("{candidate}")).unwrap();
 92              assert_eq!(candidate, candidate_recovered);
 93          }
 94          Ok(())
 95      }
 96  
 97      #[test]
 98      fn test_parse_unsupported_code_points() -> Result<()> {
 99          const UNSUPPORTED_CODE_POINTS: [&str; 9] = [
100              "\u{202a}", "\u{202b}", "\u{202c}", "\u{202d}", "\u{202e}", "\u{2066}", "\u{2067}", "\u{2068}", "\u{2069}",
101          ];
102  
103          // Ensure that the invalid code point is not allowed in the string.
104          for unsupported_code_point in UNSUPPORTED_CODE_POINTS {
105              assert!(StringType::<CurrentEnvironment>::parse(unsupported_code_point).is_err());
106          }
107  
108          Ok(())
109      }
110  }