Skip to main content

snarkvm_synthesizer_program/view/output/
parse.rs

1// Copyright (c) 2019-2026 Provable Inc.
2// This file is part of the snarkVM 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
16use super::*;
17
18impl<N: Network> Parser for Output<N> {
19    /// Parses a string into an output statement.
20    /// The output statement is of the form `output {operand} as {finalize_type};`.
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 output 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 operand from the string.
30        let (string, operand) = Operand::parse(string)?;
31        // Parse the whitespace from the string.
32        let (string, _) = Sanitizer::parse_whitespaces(string)?;
33        // Parse the "as" from the string.
34        let (string, _) = tag("as")(string)?;
35        // Parse the whitespace from the string.
36        let (string, _) = Sanitizer::parse_whitespaces(string)?;
37        // Parse the finalize type from the string.
38        let (string, finalize_type) = FinalizeType::parse(string)?;
39        // Parse the whitespace from the string.
40        let (string, _) = Sanitizer::parse_whitespaces(string)?;
41        // Parse the semicolon from the string.
42        let (string, _) = tag(";")(string)?;
43        Ok((string, Self { operand, finalize_type }))
44    }
45}
46
47impl<N: Network> FromStr for Output<N> {
48    type Err = Error;
49
50    #[inline]
51    fn from_str(string: &str) -> Result<Self> {
52        match Self::parse(string) {
53            Ok((remainder, object)) => {
54                ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
55                Ok(object)
56            }
57            Err(error) => bail!("Failed to parse string. {error}"),
58        }
59    }
60}
61
62impl<N: Network> Debug for Output<N> {
63    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
64        Display::fmt(self, f)
65    }
66}
67
68impl<N: Network> Display for Output<N> {
69    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
70        write!(
71            f,
72            "{type_} {operand} as {finalize_type};",
73            type_ = Self::type_name(),
74            operand = self.operand,
75            finalize_type = self.finalize_type,
76        )
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    use console::network::MainnetV0;
84
85    type CurrentNetwork = MainnetV0;
86
87    #[test]
88    fn test_output_parse() -> Result<()> {
89        // Register operand.
90        let output = Output::<CurrentNetwork>::parse("output r0 as field.public;").unwrap().1;
91        assert_eq!(output.operand(), &Operand::<CurrentNetwork>::from_str("r0")?);
92        assert_eq!(output.finalize_type(), &FinalizeType::<CurrentNetwork>::from_str("field.public")?);
93
94        // Literal operand.
95        let output = Output::<CurrentNetwork>::parse("output 1u64 as u64.public;").unwrap().1;
96        assert_eq!(output.operand(), &Operand::<CurrentNetwork>::from_str("1u64")?);
97        assert_eq!(output.finalize_type(), &FinalizeType::<CurrentNetwork>::from_str("u64.public")?);
98
99        Ok(())
100    }
101
102    #[test]
103    fn test_output_display() -> Result<()> {
104        let output = Output::<CurrentNetwork>::from_str("output r0 as field.public;")?;
105        assert_eq!("output r0 as field.public;", output.to_string());
106
107        let output = Output::<CurrentNetwork>::from_str("output 1u64 as u64.public;")?;
108        assert_eq!("output 1u64 as u64.public;", output.to_string());
109
110        Ok(())
111    }
112
113    #[test]
114    fn test_output_parse_fails() {
115        // Missing trailing semicolon.
116        assert!(Output::<CurrentNetwork>::from_str("output r0 as field.public").is_err());
117        // Missing 'as' keyword.
118        assert!(Output::<CurrentNetwork>::from_str("output r0 field.public;").is_err());
119        // Missing operand.
120        assert!(Output::<CurrentNetwork>::from_str("output as field.public;").is_err());
121        // Missing 'output' keyword.
122        assert!(Output::<CurrentNetwork>::from_str("r0 as field.public;").is_err());
123        // Missing finalize type.
124        assert!(Output::<CurrentNetwork>::from_str("output r0 as ;").is_err());
125    }
126}