parse.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 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 PlaintextType<N> { 19 /// Parses a string into a plaintext type. 20 #[inline] 21 fn parse(string: &str) -> ParserResult<Self> { 22 // Parse to determine the plaintext type (order matters). 23 alt(( 24 map(ArrayType::parse, |type_| Self::Array(type_)), 25 map(Identifier::parse, |identifier| Self::Struct(identifier)), 26 map(LiteralType::parse, |type_| Self::Literal(type_)), 27 ))(string) 28 } 29 } 30 31 impl<N: Network> FromStr for PlaintextType<N> { 32 type Err = Error; 33 34 /// Returns a plaintext type from a string literal. 35 fn from_str(string: &str) -> Result<Self> { 36 match Self::parse(string) { 37 Ok((remainder, object)) => { 38 // Ensure the remainder is empty. 39 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 40 // Return the object. 41 Ok(object) 42 } 43 Err(error) => bail!("Failed to parse string. {error}"), 44 } 45 } 46 } 47 48 impl<N: Network> Debug for PlaintextType<N> { 49 /// Prints the plaintext type as a string. 50 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 51 Display::fmt(self, f) 52 } 53 } 54 55 impl<N: Network> Display for PlaintextType<N> { 56 /// Prints the plaintext type as a string. 57 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 58 match self { 59 // Prints the literal, i.e. field 60 Self::Literal(literal) => Display::fmt(literal, f), 61 // Prints the struct, i.e. signature 62 Self::Struct(struct_) => Display::fmt(struct_, f), 63 // Prints the array type, i.e. [field; 2u32] 64 Self::Array(array) => Display::fmt(array, f), 65 } 66 } 67 } 68 69 #[cfg(test)] 70 mod tests { 71 use super::*; 72 use alphavm_console_network::MainnetV0; 73 74 type CurrentNetwork = MainnetV0; 75 76 #[test] 77 fn test_parse() -> Result<()> { 78 assert_eq!( 79 PlaintextType::parse("field"), 80 Ok(("", PlaintextType::<CurrentNetwork>::Literal(LiteralType::Field))) 81 ); 82 assert_eq!( 83 PlaintextType::parse("signature"), 84 Ok(("", PlaintextType::<CurrentNetwork>::Literal(LiteralType::Signature))) 85 ); 86 assert_eq!( 87 PlaintextType::parse("foo"), 88 Ok(("", PlaintextType::<CurrentNetwork>::Struct(Identifier::from_str("foo")?))) 89 ); 90 assert_eq!( 91 PlaintextType::parse("u8jdsklaj"), 92 Ok(("", PlaintextType::<CurrentNetwork>::Struct(Identifier::from_str("u8jdsklaj")?))) 93 ); 94 assert_eq!( 95 PlaintextType::parse("[field; 1u32]"), 96 Ok(("", PlaintextType::<CurrentNetwork>::Array(ArrayType::from_str("[field; 1u32]")?))) 97 ); 98 Ok(()) 99 } 100 101 #[test] 102 fn test_parse_fails() -> Result<()> { 103 // Literal type must not contain visibility. 104 assert_eq!( 105 Ok((".constant", PlaintextType::<CurrentNetwork>::from_str("field")?)), 106 PlaintextType::<CurrentNetwork>::parse("field.constant") 107 ); 108 assert_eq!( 109 Ok((".public", PlaintextType::<CurrentNetwork>::from_str("field")?)), 110 PlaintextType::<CurrentNetwork>::parse("field.public") 111 ); 112 assert_eq!( 113 Ok((".private", PlaintextType::<CurrentNetwork>::from_str("field")?)), 114 PlaintextType::<CurrentNetwork>::parse("field.private") 115 ); 116 117 // Struct type must not contain visibility. 118 assert_eq!( 119 Ok((".constant", Identifier::<CurrentNetwork>::from_str("foo")?)), 120 Identifier::<CurrentNetwork>::parse("foo.constant") 121 ); 122 assert_eq!( 123 Ok((".public", Identifier::<CurrentNetwork>::from_str("foo")?)), 124 Identifier::<CurrentNetwork>::parse("foo.public") 125 ); 126 assert_eq!( 127 Ok((".private", Identifier::<CurrentNetwork>::from_str("foo")?)), 128 Identifier::<CurrentNetwork>::parse("foo.private") 129 ); 130 131 // Array type must not contain visibility. 132 assert_eq!( 133 Ok((".constant", PlaintextType::<CurrentNetwork>::from_str("[field; 1u32]")?)), 134 PlaintextType::<CurrentNetwork>::parse("[field; 1u32].constant") 135 ); 136 assert_eq!( 137 Ok((".public", PlaintextType::<CurrentNetwork>::from_str("[field; 1u32]")?)), 138 PlaintextType::<CurrentNetwork>::parse("[field; 1u32].public") 139 ); 140 assert_eq!( 141 Ok((".private", PlaintextType::<CurrentNetwork>::from_str("[field; 1u32]")?)), 142 PlaintextType::<CurrentNetwork>::parse("[field; 1u32].private") 143 ); 144 145 // Must be non-empty. 146 assert!(PlaintextType::<CurrentNetwork>::parse("").is_err()); 147 assert!(PlaintextType::<CurrentNetwork>::parse("{}").is_err()); 148 149 // Invalid characters. 150 assert!(PlaintextType::<CurrentNetwork>::parse("_").is_err()); 151 assert!(PlaintextType::<CurrentNetwork>::parse("__").is_err()); 152 assert!(PlaintextType::<CurrentNetwork>::parse("___").is_err()); 153 assert!(PlaintextType::<CurrentNetwork>::parse("-").is_err()); 154 assert!(PlaintextType::<CurrentNetwork>::parse("--").is_err()); 155 assert!(PlaintextType::<CurrentNetwork>::parse("---").is_err()); 156 assert!(PlaintextType::<CurrentNetwork>::parse("*").is_err()); 157 assert!(PlaintextType::<CurrentNetwork>::parse("**").is_err()); 158 assert!(PlaintextType::<CurrentNetwork>::parse("***").is_err()); 159 160 // Must not start with a number. 161 assert!(PlaintextType::<CurrentNetwork>::parse("1").is_err()); 162 assert!(PlaintextType::<CurrentNetwork>::parse("2").is_err()); 163 assert!(PlaintextType::<CurrentNetwork>::parse("3").is_err()); 164 assert!(PlaintextType::<CurrentNetwork>::parse("1foo").is_err()); 165 assert!(PlaintextType::<CurrentNetwork>::parse("12").is_err()); 166 assert!(PlaintextType::<CurrentNetwork>::parse("111").is_err()); 167 168 // Struct types must fit within the data capacity of a base field element. 169 let struct_ = PlaintextType::<CurrentNetwork>::parse( 170 "foo_bar_baz_qux_quux_quuz_corge_grault_garply_waldo_fred_plugh_xyzzy", 171 ); 172 assert!(struct_.is_err()); 173 174 Ok(()) 175 } 176 177 #[test] 178 fn test_display() -> Result<()> { 179 assert_eq!(PlaintextType::<CurrentNetwork>::Literal(LiteralType::Boolean).to_string(), "boolean"); 180 assert_eq!(PlaintextType::<CurrentNetwork>::Literal(LiteralType::Field).to_string(), "field"); 181 assert_eq!(PlaintextType::<CurrentNetwork>::Literal(LiteralType::Signature).to_string(), "signature"); 182 assert_eq!(PlaintextType::<CurrentNetwork>::Struct(Identifier::from_str("foo")?).to_string(), "foo"); 183 assert_eq!(PlaintextType::<CurrentNetwork>::Struct(Identifier::from_str("bar")?).to_string(), "bar"); 184 assert_eq!( 185 PlaintextType::<CurrentNetwork>::Array(ArrayType::from_str("[field; 8u32]")?).to_string(), 186 "[field; 8u32]" 187 ); 188 Ok(()) 189 } 190 }