parse.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm 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 {plaintext_type}.public;`. 21 /// 22 /// # Errors 23 /// This finalize 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 finalize type from the string. 47 let (string, finalize_type) = FinalizeType::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, finalize_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!(f, "{} {} as {};", Self::type_name(), self.register, self.finalize_type) 86 } 87 } 88 89 #[cfg(test)] 90 mod tests { 91 use super::*; 92 use console::network::MainnetV0; 93 94 type CurrentNetwork = MainnetV0; 95 96 #[test] 97 fn test_input_parse() -> Result<()> { 98 // Literal 99 let input = Input::<CurrentNetwork>::parse("input r0 as field.public;").unwrap().1; 100 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(0)); 101 assert_eq!(input.finalize_type(), &FinalizeType::<CurrentNetwork>::from_str("field.public")?); 102 103 // Struct 104 let input = Input::<CurrentNetwork>::parse("input r1 as signature.public;").unwrap().1; 105 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(1)); 106 assert_eq!(input.finalize_type(), &FinalizeType::<CurrentNetwork>::from_str("signature.public")?); 107 108 // Record 109 let input = Input::<CurrentNetwork>::parse("input r2 as token.public;").unwrap().1; 110 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(2)); 111 assert_eq!(input.finalize_type(), &FinalizeType::<CurrentNetwork>::from_str("token.public")?); 112 113 // Future 114 let input = Input::<CurrentNetwork>::parse("input r3 as credits.delta/mint_public.future;").unwrap().1; 115 assert_eq!(input.register(), &Register::<CurrentNetwork>::Locator(3)); 116 assert_eq!( 117 input.finalize_type(), 118 &FinalizeType::<CurrentNetwork>::from_str("credits.delta/mint_public.future")? 119 ); 120 121 Ok(()) 122 } 123 124 #[test] 125 fn test_input_display() -> Result<()> { 126 // Literal 127 let input = Input::<CurrentNetwork>::from_str("input r0 as field.public;")?; 128 assert_eq!("input r0 as field.public;", input.to_string()); 129 130 // Struct 131 let input = Input::<CurrentNetwork>::from_str("input r1 as signature.public;")?; 132 assert_eq!("input r1 as signature.public;", input.to_string()); 133 134 // Record 135 let input = Input::<CurrentNetwork>::parse("input r2 as token.public;").unwrap().1; 136 assert_eq!(format!("{input}"), "input r2 as token.public;"); 137 138 Ok(()) 139 } 140 }