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 use crate::Command; 18 19 impl<N: Network> Parser for FinalizeCore<N> { 20 /// Parses a string into finalize. 21 #[inline] 22 fn parse(string: &str) -> ParserResult<Self> { 23 // Parse the whitespace and comments from the string. 24 let (string, _) = Sanitizer::parse(string)?; 25 // Parse the 'finalize' keyword from the string. 26 let (string, _) = tag(Self::type_name())(string)?; 27 // Parse the whitespace from the string. 28 let (string, _) = Sanitizer::parse_whitespaces(string)?; 29 // Parse the associated function name from the string. 30 let (string, name) = Identifier::<N>::parse(string)?; 31 // Parse the whitespace from the string. 32 let (string, _) = Sanitizer::parse_whitespaces(string)?; 33 // Parse the colon ':' keyword from the string. 34 let (string, _) = tag(":")(string)?; 35 36 // Parse the inputs from the string. 37 let (string, inputs) = many0(Input::parse)(string)?; 38 // Parse the commands from the string. 39 let (string, commands) = many1(Command::<N>::parse)(string)?; 40 41 map_res(take(0usize), move |_| { 42 // Initialize a new finalize. 43 let mut finalize = Self::new(name); 44 if let Err(error) = inputs.iter().cloned().try_for_each(|input| finalize.add_input(input)) { 45 eprintln!("{error}"); 46 return Err(error); 47 } 48 if let Err(error) = commands.iter().cloned().try_for_each(|command| finalize.add_command(command)) { 49 eprintln!("{error}"); 50 return Err(error); 51 } 52 Ok::<_, Error>(finalize) 53 })(string) 54 } 55 } 56 57 impl<N: Network> FromStr for FinalizeCore<N> { 58 type Err = Error; 59 60 /// Returns a finalize from a string literal. 61 fn from_str(string: &str) -> Result<Self> { 62 match Self::parse(string) { 63 Ok((remainder, object)) => { 64 // Ensure the remainder is empty. 65 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 66 // Return the object. 67 Ok(object) 68 } 69 Err(error) => bail!("Failed to parse string. {error}"), 70 } 71 } 72 } 73 74 impl<N: Network> Debug for FinalizeCore<N> { 75 /// Prints the finalize as a string. 76 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 77 Display::fmt(self, f) 78 } 79 } 80 81 impl<N: Network> Display for FinalizeCore<N> { 82 /// Prints the finalize as a string. 83 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 84 // Write the finalize to a string. 85 write!(f, "{} {}:", Self::type_name(), self.name)?; 86 self.inputs.iter().try_for_each(|input| write!(f, "\n {input}"))?; 87 self.commands.iter().try_for_each(|command| write!(f, "\n {command}")) 88 } 89 } 90 91 #[cfg(test)] 92 mod tests { 93 use super::*; 94 use crate::Finalize; 95 use console::network::MainnetV0; 96 97 type CurrentNetwork = MainnetV0; 98 99 #[test] 100 fn test_finalize_parse() { 101 let finalize = Finalize::<CurrentNetwork>::parse( 102 r" 103 finalize foo: 104 input r0 as field.public; 105 input r1 as field.public; 106 add r0 r1 into r2;", 107 ) 108 .unwrap() 109 .1; 110 assert_eq!("foo", finalize.name().to_string()); 111 assert_eq!(2, finalize.inputs().len()); 112 assert_eq!(1, finalize.commands().len()); 113 114 // Finalize with 0 inputs. 115 let finalize = Finalize::<CurrentNetwork>::parse( 116 r" 117 finalize foo: 118 add 1u32 2u32 into r0;", 119 ) 120 .unwrap() 121 .1; 122 assert_eq!("foo", finalize.name().to_string()); 123 assert_eq!(0, finalize.inputs().len()); 124 assert_eq!(1, finalize.commands().len()); 125 } 126 127 #[test] 128 fn test_finalize_parse_cast() { 129 let finalize = Finalize::<CurrentNetwork>::parse( 130 r" 131 finalize foo: 132 input r0 as token.public; 133 cast r0.owner r0.token_amount into r1 as token;", 134 ) 135 .unwrap() 136 .1; 137 assert_eq!("foo", finalize.name().to_string()); 138 assert_eq!(1, finalize.inputs().len()); 139 assert_eq!(1, finalize.commands().len()); 140 } 141 142 #[test] 143 fn test_finalize_display() { 144 let expected = r"finalize foo: 145 input r0 as field.public; 146 input r1 as field.public; 147 add r0 r1 into r2;"; 148 let finalize = Finalize::<CurrentNetwork>::parse(expected).unwrap().1; 149 assert_eq!(expected, format!("{finalize}"),); 150 } 151 }