/ console / program / src / data / access / 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 Access<N> {
 22      fn parse(string: &str) -> ParserResult<'_, Self> {
 23          alt((
 24              map(pair(tag("["), pair(U32::parse, tag("]"))), |(_, (index, _))| Self::Index(index)),
 25              map(pair(tag("."), Identifier::parse), |(_, identifier)| Self::Member(identifier)),
 26          ))(string)
 27      }
 28  }
 29  
 30  impl<N: Network> FromStr for Access<N> {
 31      type Err = Error;
 32  
 33      /// Parses an identifier into an access.
 34      #[inline]
 35      fn from_str(string: &str) -> Result<Self> {
 36          match Self::parse(string) {
 37              Ok((remainder, object)) => {
 38                  // Ensure the remainder is empty.
 39                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
 40                  // Return the object.
 41                  Ok(object)
 42              }
 43              Err(error) => bail!("Failed to parse string. {error}"),
 44          }
 45      }
 46  }
 47  
 48  impl<N: Network> Debug for Access<N> {
 49      /// Prints the access as a string.
 50      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 51          Display::fmt(self, f)
 52      }
 53  }
 54  
 55  impl<N: Network> Display for Access<N> {
 56      /// Prints the access as a string.
 57      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
 58          match self {
 59              // Prints the access member, i.e. `.foo`
 60              Self::Member(identifier) => write!(f, ".{identifier}"),
 61              // Prints the access index, i.e. `[0u32]`
 62              Self::Index(index) => write!(f, "[{index}]"),
 63          }
 64      }
 65  }
 66  
 67  #[cfg(test)]
 68  mod tests {
 69      use super::*;
 70      use alphavm_console_network::MainnetV0;
 71  
 72      type CurrentNetwork = MainnetV0;
 73  
 74      #[test]
 75      fn test_parse() -> Result<()> {
 76          assert_eq!(Access::parse(".data"), Ok(("", Access::<CurrentNetwork>::Member(Identifier::from_str("data")?))));
 77          assert_eq!(Access::parse("[0u32]"), Ok(("", Access::<CurrentNetwork>::Index(U32::new(0)))));
 78          Ok(())
 79      }
 80  
 81      #[test]
 82      fn test_parse_fails() -> Result<()> {
 83          // Must be non-empty.
 84          assert!(Access::<CurrentNetwork>::parse("").is_err());
 85          assert!(Access::<CurrentNetwork>::parse(".").is_err());
 86          assert!(Access::<CurrentNetwork>::parse("[]").is_err());
 87  
 88          // Invalid accesses.
 89          assert!(Access::<CurrentNetwork>::parse(".0").is_err());
 90          assert!(Access::<CurrentNetwork>::parse("[index]").is_err());
 91          assert!(Access::<CurrentNetwork>::parse("[0.0]").is_err());
 92          assert!(Access::<CurrentNetwork>::parse("[999999999999]").is_err());
 93  
 94          // Must fit within the data capacity of a base field element.
 95          let access =
 96              Access::<CurrentNetwork>::parse(".foo_bar_baz_qux_quux_quuz_corge_grault_garply_waldo_fred_plugh_xyzzy");
 97          assert!(access.is_err());
 98  
 99          Ok(())
100      }
101  
102      #[test]
103      fn test_display() -> Result<()> {
104          assert_eq!(Access::<CurrentNetwork>::Member(Identifier::from_str("foo")?).to_string(), ".foo");
105          assert_eq!(Access::<CurrentNetwork>::Index(U32::new(0)).to_string(), "[0u32]");
106          Ok(())
107      }
108  }