snarkvm_console_program/data/record/
parse_plaintext.rs1use super::*;
17
18impl<N: Network> Parser for Record<N, Plaintext<N>> {
19 #[inline]
21 fn parse(string: &str) -> ParserResult<Self> {
22 #[allow(clippy::type_complexity)]
24 fn parse_pair<N: Network>(string: &str) -> ParserResult<(Identifier<N>, Entry<N, Plaintext<N>>)> {
25 let (string, _) = Sanitizer::parse(string)?;
27 let (string, identifier) = Identifier::parse(string)?;
29 let (string, _) = Sanitizer::parse_whitespaces(string)?;
31 let (string, _) = tag(":")(string)?;
33 let (string, _) = Sanitizer::parse(string)?;
35 let (string, entry) = Entry::parse(string)?;
37 let (string, _) = Sanitizer::parse_whitespaces(string)?;
39 Ok((string, (identifier, entry)))
41 }
42
43 let (string, _) = Sanitizer::parse(string)?;
45 let (string, _) = tag("{")(string)?;
47
48 let (string, _) = Sanitizer::parse(string)?;
50 let (string, _) = tag("owner")(string)?;
52 let (string, _) = Sanitizer::parse_whitespaces(string)?;
54 let (string, _) = tag(":")(string)?;
56 let (string, _) = Sanitizer::parse(string)?;
58 let (string, owner) = alt((
60 map(pair(Address::parse, tag(".public")), |(owner, _)| Owner::Public(owner)),
61 map(pair(Address::parse, tag(".private")), |(owner, _)| {
62 Owner::Private(Plaintext::from(Literal::Address(owner)))
63 }),
64 ))(string)?;
65 let (string, _) = tag(",")(string)?;
67
68 let (string, entries) = map_res(separated_list0(tag(","), parse_pair), |entries: Vec<_>| {
70 let reserved = [Identifier::from_str("owner").map_err(|e| error(e.to_string()))?];
72 if has_duplicates(entries.iter().map(|(identifier, _)| identifier).chain(reserved.iter())) {
74 return Err(error("Duplicate entry type found in record"));
75 }
76 match entries.len() <= N::MAX_DATA_ENTRIES {
78 true => Ok(entries),
79 false => Err(error(format!("Found a record that exceeds size ({})", entries.len()))),
80 }
81 })(string)?;
82
83 let string = match !entries.is_empty() {
85 true => tag(",")(string)?.0,
87 false => string,
88 };
89
90 let (string, _) = Sanitizer::parse(string)?;
92 let (string, _) = tag("_nonce")(string)?;
94 let (string, _) = tag(":")(string)?;
96 let (string, _) = Sanitizer::parse(string)?;
98 let (string, (nonce, _)) = pair(Group::parse, tag(".public"))(string)?;
100
101 let (string, _) = Sanitizer::parse(string)?;
103 let (string, _) = tag("}")(string)?;
105 Ok((string, Record { owner, data: IndexMap::from_iter(entries), nonce }))
107 }
108}
109
110impl<N: Network> FromStr for Record<N, Plaintext<N>> {
111 type Err = Error;
112
113 fn from_str(string: &str) -> Result<Self> {
115 match Self::parse(string) {
116 Ok((remainder, object)) => {
117 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
119 Ok(object)
121 }
122 Err(error) => bail!("Failed to parse string. {error}"),
123 }
124 }
125}
126
127impl<N: Network> Debug for Record<N, Plaintext<N>> {
128 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
130 Display::fmt(self, f)
131 }
132}
133
134impl<N: Network> Display for Record<N, Plaintext<N>> {
135 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
137 self.fmt_internal(f, 0)
138 }
139}
140
141impl<N: Network> Record<N, Plaintext<N>> {
142 fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result {
144 const INDENT: usize = 2;
146
147 write!(f, "{{")?;
149 write!(f, "\n{:indent$}owner: {},", "", self.owner, indent = (depth + 1) * INDENT)?;
151 for (identifier, entry) in self.data.iter() {
153 write!(f, "\n{:indent$}{identifier}: ", "", indent = (depth + 1) * INDENT)?;
155 match entry {
157 Entry::Constant(Plaintext::Literal(..))
159 | Entry::Public(Plaintext::Literal(..))
160 | Entry::Private(Plaintext::Literal(..)) => write!(f, "{entry}")?,
161 Entry::Constant(Plaintext::Struct(..))
163 | Entry::Public(Plaintext::Struct(..))
164 | Entry::Private(Plaintext::Struct(..))
165 | Entry::Constant(Plaintext::Array(..))
166 | Entry::Public(Plaintext::Array(..))
167 | Entry::Private(Plaintext::Array(..)) => entry.fmt_internal(f, depth + 1)?,
168 }
169 write!(f, ",")?;
171 }
172 write!(f, "\n{:indent$}_nonce: {}.public", "", self.nonce, indent = (depth + 1) * INDENT)?;
174 write!(f, "\n{:indent$}}}", "", indent = depth * INDENT)
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182 use snarkvm_console_network::MainnetV0;
183
184 type CurrentNetwork = MainnetV0;
185
186 #[test]
187 fn test_parse_without_data_entries() -> Result<()> {
188 let expected = r"{
190 owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.private,
191 _nonce: 0group.public
192}";
193 let given =
194 "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.private, _nonce: 0group.public }";
195 let (remainder, candidate) = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(given)?;
196 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
197 assert_eq!(expected, candidate.to_string());
198 assert_eq!("", remainder);
199 Ok(())
200 }
201
202 #[test]
203 fn test_parse_with_literal_entry() -> Result<()> {
204 let expected = r"{
205 owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.public,
206 foo: 5u8.constant,
207 _nonce: 0group.public
208}";
209 let given = "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.public, foo: 5u8.constant, _nonce: 0group.public }";
210 let (remainder, candidate) = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(given)?;
211 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
212 assert_eq!(expected, candidate.to_string());
213 assert_eq!("", remainder);
214 Ok(())
215 }
216
217 #[test]
218 fn test_parse_with_struct_entry() -> Result<()> {
219 let expected = r"{
220 owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.public,
221 foo: 5u8.public,
222 bar: {
223 baz: 6u8.constant,
224 qux: 7u8.constant
225 },
226 quux: 8u8.private,
227 corge: {
228 grault: 9u8.constant,
229 garply: {
230 waldo: 10u8.constant,
231 fred: 11u8.constant
232 }
233 },
234 xyzzy: {
235 thud: 12u8.public
236 },
237 _nonce: 2293253577170800572742339369209137467208538700597121244293392265726446806023group.public
238}";
239 let (remainder, candidate) = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(expected)?;
240 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
241 assert_eq!(expected, candidate.to_string());
242 assert_eq!("", remainder);
243
244 let expected = r"{
245 owner: aleo1lhcpfumagern97esytsgdva2ytme043zydlzyprhejsd0gw5vypqqz0zkw.private,
246 foo: {
247 bar: 0u128.private
248 },
249 baz: {
250 quine: {
251 flop: 0u64.private
252 },
253 slice: 0u16.private,
254 flag: true.private,
255 square: {
256 first: 0u128.private,
257 second: 1u128.private,
258 third: 2u128.private,
259 fourth: 3u128.private
260 }
261 },
262 _nonce: 0group.public
263}";
264 let (remainder, candidate) = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(expected)?;
265 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
266 assert_eq!(expected, candidate.to_string());
267 assert_eq!("", remainder);
268
269 let expected = r"{
270 owner: aleo18ttcegpydcs95yw4je0u400j3u7r26yqr9h8evqps3qa9slrvyrsqjwt9l.private,
271 c: {
272 c: {
273 a: 0u8.private,
274 b: 1u8.private
275 },
276 d: {
277 a: 0u8.private,
278 b: 1u8.private
279 }
280 },
281 d: {
282 c: {
283 a: 0u8.private,
284 b: 1u8.private
285 },
286 d: {
287 a: 0u8.private,
288 b: 1u8.private
289 }
290 },
291 _nonce: 8102307625287186026775464343238779600702564007094834161216556016558567413871group.public
292}";
293 let (remainder, candidate) = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(expected)?;
294 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
295 assert_eq!(expected, candidate.to_string());
296 assert_eq!("", remainder);
297
298 Ok(())
299 }
300
301 #[test]
302 fn test_parse_with_array_entry() -> Result<()> {
303 let expected = r"{
304 owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.public,
305 foo: 5u8.public,
306 bar: [
307 6u8.private,
308 7u8.private,
309 8u8.private
310 ],
311 _nonce: 0group.public
312}";
313 let (remainder, candidate) = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::parse(expected)?;
314 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
315 assert_eq!(expected, candidate.to_string());
316 assert_eq!("", remainder);
317 Ok(())
318 }
319
320 #[test]
321 fn test_parse_fails() -> Result<()> {
322 let expected = "{ foo: 5u8.private, _nonce: 0group.public }";
324 assert!(Plaintext::<CurrentNetwork>::parse(expected).is_err());
325
326 let expected =
328 "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.public, foo: 5u8.private }";
329 assert!(Plaintext::<CurrentNetwork>::parse(expected).is_err());
330
331 let expected = r"{
333 owner: aleo14tlamssdmg3d0p5zmljma573jghe2q9n6wz29qf36re2glcedcpqfg4add.private,
334 a: true.private,
335 b: 123456789field.private,
336 c: 0group.private,
337 d: {
338 e: true.private,
339 f: 123456789field.public,
340 g: 0group.private
341 },
342 _nonce: 0group.public
343}";
344 assert!(Plaintext::<CurrentNetwork>::parse(expected).is_err());
345 Ok(())
346 }
347}