parse.rs
1 // Copyright (c) 2025 ADnet Contributors 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 Input<N> { 19 /// Parses a string into an input statement. 20 /// The input statement is of the form `input {register} as {register_type};`. 21 /// 22 /// # Errors 23 /// This function will halt if the given register is a register member. 24 #[inline] 25 fn parse(string: &str) -> ParserResult<Self> { 26 // Parse the whitespace and comments from the string. 27 let (string, _) = Sanitizer::parse(string)?; 28 // Parse the input keyword from the string. 29 let (string, _) = tag(Self::type_name())(string)?; 30 // Parse the whitespace from the string. 31 let (string, _) = Sanitizer::parse_whitespaces(string)?; 32 // Parse the register from the string. 33 let (string, register) = map_res(Register::parse, |register| { 34 // Ensure the register is not a register member. 35 match ®ister { 36 Register::Locator(..) => Ok(register), 37 Register::Access(..) => Err(error(format!("Input register {register} cannot be a register member"))), 38 } 39 })(string)?; 40 // Parse the whitespace from the string. 41 let (string, _) = Sanitizer::parse_whitespaces(string)?; 42 // Parse the "as" from the string. 43 let (string, _) = tag("as")(string)?; 44 // Parse the whitespace from the string. 45 let (string, _) = Sanitizer::parse_whitespaces(string)?; 46 // Parse the register type from the string. 47 let (string, register_type) = RegisterType::parse(string)?; 48 // Parse the whitespace from the string. 49 let (string, _) = Sanitizer::parse_whitespaces(string)?; 50 // Parse the semicolon from the string. 51 let (string, _) = tag(";")(string)?; 52 // Return the input statement. 53 Ok((string, Self { register, register_type })) 54 } 55 } 56 57 impl<N: Network> FromStr for Input<N> { 58 type Err = Error; 59 60 /// Parses a string into an input statement. 61 #[inline] 62 fn from_str(string: &str) -> Result<Self> { 63 match Self::parse(string) { 64 Ok((remainder, object)) => { 65 // Ensure the remainder is empty. 66 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 67 // Return the object. 68 Ok(object) 69 } 70 Err(error) => bail!("Failed to parse string. {error}"), 71 } 72 } 73 } 74 75 impl<N: Network> Debug for Input<N> { 76 /// Prints the input as a string. 77 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 78 Display::fmt(self, f) 79 } 80 } 81 82 impl<N: Network> Display for Input<N> { 83 /// Prints the input statement as a string. 84 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 85 write!( 86 f, 87 "{type_} {register} as {register_type};", 88 type_ = Self::type_name(), 89 register = self.register, 90 register_type = self.register_type 91 ) 92 } 93 } 94 95 #[cfg(test)] 96 mod tests { 97 use super::*; 98 use console::network::MainnetV0; 99 100 type CurrentNetwork = MainnetV0; 101 102 #[test] 103 fn test_input_parse() -> Result<()> { 104 // Literal 105 let input = Input::<CurrentNetwork>::parse("input r0 as field;").unwrap().1; 106 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(0)); 107 assert_eq!(input.register_type(), &RegisterType::<CurrentNetwork>::from_str("field")?); 108 109 // Struct 110 let input = Input::<CurrentNetwork>::parse("input r1 as signature;").unwrap().1; 111 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(1)); 112 assert_eq!(input.register_type(), &RegisterType::<CurrentNetwork>::from_str("signature")?); 113 114 // Record 115 let input = Input::<CurrentNetwork>::parse("input r2 as token.record;").unwrap().1; 116 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(2)); 117 assert_eq!(input.register_type(), &RegisterType::<CurrentNetwork>::from_str("token.record")?); 118 119 Ok(()) 120 } 121 122 #[test] 123 fn test_input_display() -> Result<()> { 124 // Literal 125 let input = Input::<CurrentNetwork>::from_str("input r0 as field;")?; 126 assert_eq!("input r0 as field;", input.to_string()); 127 128 // Struct 129 let input = Input::<CurrentNetwork>::from_str("input r1 as signature;")?; 130 assert_eq!("input r1 as signature;", input.to_string()); 131 132 // Record 133 let input = Input::<CurrentNetwork>::parse("input r2 as token.record;").unwrap().1; 134 assert_eq!(format!("{input}"), "input r2 as token.record;"); 135 136 Ok(()) 137 } 138 }