parse.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the alphavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 use super::*; 17 18 impl<N: Network> Parser for Access<N> { 19 fn parse(string: &str) -> ParserResult<Self> { 20 alt(( 21 map(pair(tag("["), pair(U32::parse, tag("]"))), |(_, (index, _))| Self::Index(index)), 22 map(pair(tag("."), Identifier::parse), |(_, identifier)| Self::Member(identifier)), 23 ))(string) 24 } 25 } 26 27 impl<N: Network> FromStr for Access<N> { 28 type Err = Error; 29 30 /// Parses an identifier into an access. 31 #[inline] 32 fn from_str(string: &str) -> Result<Self> { 33 match Self::parse(string) { 34 Ok((remainder, object)) => { 35 // Ensure the remainder is empty. 36 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 37 // Return the object. 38 Ok(object) 39 } 40 Err(error) => bail!("Failed to parse string. {error}"), 41 } 42 } 43 } 44 45 impl<N: Network> Debug for Access<N> { 46 /// Prints the access as a string. 47 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 48 Display::fmt(self, f) 49 } 50 } 51 52 impl<N: Network> Display for Access<N> { 53 /// Prints the access as a string. 54 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 55 match self { 56 // Prints the access member, i.e. `.foo` 57 Self::Member(identifier) => write!(f, ".{identifier}"), 58 // Prints the access index, i.e. `[0u32]` 59 Self::Index(index) => write!(f, "[{index}]"), 60 } 61 } 62 } 63 64 #[cfg(test)] 65 mod tests { 66 use super::*; 67 use alphavm_console_network::MainnetV0; 68 69 type CurrentNetwork = MainnetV0; 70 71 #[test] 72 fn test_parse() -> Result<()> { 73 assert_eq!(Access::parse(".data"), Ok(("", Access::<CurrentNetwork>::Member(Identifier::from_str("data")?)))); 74 assert_eq!(Access::parse("[0u32]"), Ok(("", Access::<CurrentNetwork>::Index(U32::new(0))))); 75 Ok(()) 76 } 77 78 #[test] 79 fn test_parse_fails() -> Result<()> { 80 // Must be non-empty. 81 assert!(Access::<CurrentNetwork>::parse("").is_err()); 82 assert!(Access::<CurrentNetwork>::parse(".").is_err()); 83 assert!(Access::<CurrentNetwork>::parse("[]").is_err()); 84 85 // Invalid accesses. 86 assert!(Access::<CurrentNetwork>::parse(".0").is_err()); 87 assert!(Access::<CurrentNetwork>::parse("[index]").is_err()); 88 assert!(Access::<CurrentNetwork>::parse("[0.0]").is_err()); 89 assert!(Access::<CurrentNetwork>::parse("[999999999999]").is_err()); 90 91 // Must fit within the data capacity of a base field element. 92 let access = 93 Access::<CurrentNetwork>::parse(".foo_bar_baz_qux_quux_quuz_corge_grault_garply_waldo_fred_plugh_xyzzy"); 94 assert!(access.is_err()); 95 96 Ok(()) 97 } 98 99 #[test] 100 fn test_display() -> Result<()> { 101 assert_eq!(Access::<CurrentNetwork>::Member(Identifier::from_str("foo")?).to_string(), ".foo"); 102 assert_eq!(Access::<CurrentNetwork>::Index(U32::new(0)).to_string(), "[0u32]"); 103 Ok(()) 104 } 105 }