/ synthesizer / program / src / finalize / input / parse.rs
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 &register {
 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  }