1use super::*;
17
18impl<N: Network> Parser for Plaintext<N> {
19 #[inline]
21 fn parse(string: &str) -> ParserResult<Self> {
22 fn parse_pair<N: Network>(string: &str) -> ParserResult<(Identifier<N>, Plaintext<N>)> {
24 let (string, _) = Sanitizer::parse(string)?;
26 let (string, identifier) = Identifier::parse(string)?;
28 let (string, _) = Sanitizer::parse_whitespaces(string)?;
30 let (string, _) = tag(":")(string)?;
32 let (string, plaintext) = Plaintext::parse(string)?;
34 let (string, _) = Sanitizer::parse_whitespaces(string)?;
36 Ok((string, (identifier, plaintext)))
38 }
39
40 fn parse_struct<N: Network>(string: &str) -> ParserResult<Plaintext<N>> {
42 let (string, _) = Sanitizer::parse(string)?;
44 let (string, _) = tag("{")(string)?;
46 let (string, members) = map_res(separated_list1(tag(","), parse_pair), |members: Vec<_>| {
48 if has_duplicates(members.iter().map(|(name, ..)| name)) {
50 return Err(error("Duplicate member in struct"));
51 }
52 match members.len() <= N::MAX_STRUCT_ENTRIES {
54 true => Ok(members),
55 false => Err(error(format!("Found a plaintext that exceeds size ({})", members.len()))),
56 }
57 })(string)?;
58 let (string, _) = Sanitizer::parse(string)?;
60 let (string, _) = tag("}")(string)?;
62 Ok((string, Plaintext::Struct(IndexMap::from_iter(members), Default::default())))
64 }
65
66 fn parse_array<N: Network>(string: &str) -> ParserResult<Plaintext<N>> {
68 let (string, _) = Sanitizer::parse(string)?;
70 let (string, _) = tag("[")(string)?;
72 let (string, members) = separated_list1(tag(","), Plaintext::parse)(string)?;
74 let (string, _) = Sanitizer::parse(string)?;
76 let (string, _) = tag("]")(string)?;
78 Ok((string, Plaintext::Array(members, Default::default())))
80 }
81
82 let (string, _) = Sanitizer::parse_whitespaces(string)?;
84 alt((
86 map(Literal::parse, |literal| Self::Literal(literal, Default::default())),
88 parse_struct,
90 parse_array,
92 ))(string)
93 }
94}
95
96impl<N: Network> FromStr for Plaintext<N> {
97 type Err = Error;
98
99 fn from_str(string: &str) -> Result<Self> {
101 match Self::parse(string) {
102 Ok((remainder, object)) => {
103 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
105 Ok(object)
107 }
108 Err(error) => bail!("Failed to parse string. {error}"),
109 }
110 }
111}
112
113impl<N: Network> Debug for Plaintext<N> {
114 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
116 Display::fmt(self, f)
117 }
118}
119
120impl<N: Network> Display for Plaintext<N> {
121 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
123 self.fmt_internal(f, 0)
124 }
125}
126
127impl<N: Network> Plaintext<N> {
128 fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result {
130 const INDENT: usize = 2;
132
133 match self {
134 Self::Literal(literal, ..) => write!(f, "{:indent$}{literal}", "", indent = depth * INDENT),
136 Self::Struct(struct_, ..) => {
138 write!(f, "{{")?;
140 struct_.iter().enumerate().try_for_each(|(i, (name, plaintext))| {
142 match plaintext {
143 Self::Literal(literal, ..) => match i == struct_.len() - 1 {
144 true => {
145 write!(f, "\n{:indent$}{name}: {literal}", "", indent = (depth + 1) * INDENT)?;
147 write!(f, "\n{:indent$}}}", "", indent = depth * INDENT)
149 }
150 false => write!(f, "\n{:indent$}{name}: {literal},", "", indent = (depth + 1) * INDENT),
152 },
153 Self::Struct(..) | Self::Array(..) => {
154 write!(f, "\n{:indent$}{name}: ", "", indent = (depth + 1) * INDENT)?;
156 plaintext.fmt_internal(f, depth + 1)?;
158 match i == struct_.len() - 1 {
160 true => write!(f, "\n{:indent$}}}", "", indent = depth * INDENT),
162 false => write!(f, ","),
164 }
165 }
166 }
167 })
168 }
169 Self::Array(array, ..) => {
171 write!(f, "[")?;
173 array.iter().enumerate().try_for_each(|(i, plaintext)| {
175 match plaintext {
176 Self::Literal(literal, ..) => match i == array.len() - 1 {
177 true => {
178 write!(f, "\n{:indent$}{literal}", "", indent = (depth + 1) * INDENT)?;
180 write!(f, "\n{:indent$}]", "", indent = depth * INDENT)
182 }
183 false => write!(f, "\n{:indent$}{literal},", "", indent = (depth + 1) * INDENT),
185 },
186 Self::Struct(..) | Self::Array(..) => {
187 write!(f, "\n{:indent$}", "", indent = (depth + 1) * INDENT)?;
189 plaintext.fmt_internal(f, depth + 1)?;
191 match i == array.len() - 1 {
193 true => write!(f, "\n{:indent$}]", "", indent = depth * INDENT),
195 false => write!(f, ","),
197 }
198 }
199 }
200 })
201 }
202 }
203 }
204}
205
206#[cfg(test)]
207mod tests {
208 use super::*;
209 use snarkvm_console_network::MainnetV0;
210
211 type CurrentNetwork = MainnetV0;
212
213 #[test]
214 fn test_parse_literal() -> Result<()> {
215 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse("5u8")?;
217 assert_eq!("5u8", candidate.to_string());
218 assert_eq!("", remainder);
219
220 Ok(())
221 }
222
223 #[test]
224 fn test_parse_struct() -> Result<()> {
225 let expected = r"{
227 foo: 5u8
228}";
229 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse("{ foo: 5u8 }")?;
230 assert_eq!(expected, candidate.to_string());
231 assert_eq!("", remainder);
232
233 let expected = r"{
234 foo: 5u8,
235 bar: {
236 baz: 10field,
237 qux: {
238 quux: {
239 corge: {
240 grault: {
241 garply: {
242 waldo: {
243 fred: {
244 plugh: {
245 xyzzy: {
246 thud: true
247 }
248 }
249 }
250 }
251 }
252 }
253 }
254 }
255 }
256 }
257}";
258 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(
259 "{ foo: 5u8, bar: { baz: 10field, qux: {quux:{corge :{grault: {garply:{waldo:{fred:{plugh:{xyzzy: { thud: true}} }}} }}}}}}",
260 )?;
261 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
262 assert_eq!(expected, candidate.to_string());
263 assert_eq!("", remainder);
264
265 Ok(())
266 }
267
268 #[test]
269 fn test_parse_fails() {
270 assert!(Plaintext::<CurrentNetwork>::parse("").is_err());
272 assert!(Plaintext::<CurrentNetwork>::parse("{}").is_err());
273
274 assert!(Plaintext::<CurrentNetwork>::parse("_").is_err());
276 assert!(Plaintext::<CurrentNetwork>::parse("__").is_err());
277 assert!(Plaintext::<CurrentNetwork>::parse("___").is_err());
278 assert!(Plaintext::<CurrentNetwork>::parse("-").is_err());
279 assert!(Plaintext::<CurrentNetwork>::parse("--").is_err());
280 assert!(Plaintext::<CurrentNetwork>::parse("---").is_err());
281 assert!(Plaintext::<CurrentNetwork>::parse("*").is_err());
282 assert!(Plaintext::<CurrentNetwork>::parse("**").is_err());
283 assert!(Plaintext::<CurrentNetwork>::parse("***").is_err());
284
285 assert!(Plaintext::<CurrentNetwork>::parse("1").is_err());
287 assert!(Plaintext::<CurrentNetwork>::parse("2").is_err());
288 assert!(Plaintext::<CurrentNetwork>::parse("3").is_err());
289 assert!(Plaintext::<CurrentNetwork>::parse("1foo").is_err());
290 assert!(Plaintext::<CurrentNetwork>::parse("12").is_err());
291 assert!(Plaintext::<CurrentNetwork>::parse("111").is_err());
292
293 let plaintext =
295 Plaintext::<CurrentNetwork>::parse("foo_bar_baz_qux_quux_quuz_corge_grault_garply_waldo_fred_plugh_xyzzy");
296 assert!(plaintext.is_err());
297 }
298
299 #[test]
300 fn test_nested_structs1() {
301 let expected = r"{
302 r1: {
303 c1: 1u8,
304 c2: 2u8,
305 c3: 1u8
306 },
307 r2: {
308 c1: 2u8,
309 c2: 2u8,
310 c3: 1u8
311 },
312 r3: {
313 c1: 1u8,
314 c2: 2u8,
315 c3: 1u8
316 }
317}";
318
319 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
320 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
321 assert_eq!(expected, candidate.to_string());
322 assert_eq!("", remainder);
323 }
324
325 #[test]
326 fn test_nested_structs2() {
327 let expected = r"{
328 foo: {
329 bar: {
330 baz: 1u8
331 },
332 qux: {
333 quux: 2u8
334 }
335 }
336}";
337
338 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
339 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
340 assert_eq!(expected, candidate.to_string());
341 assert_eq!("", remainder);
342 }
343
344 #[test]
345 fn test_nested_structs3() {
346 let expected = r"{
347 c: {
348 a: 0u8,
349 b: 1u8
350 },
351 d: {
352 a: 0u8,
353 b: 1u8
354 }
355}";
356
357 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
358 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
359 assert_eq!(expected, candidate.to_string());
360 assert_eq!("", remainder);
361 }
362
363 #[test]
364 fn test_array() {
365 let expected = r"[
367 1u8,
368 2u8,
369 3u8
370]";
371 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
372 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
373 assert_eq!(expected, candidate.to_string());
374 assert_eq!("", remainder);
375
376 let expected = r"[
378 {
379 foo: 1u8,
380 bar: 2u8
381 },
382 {
383 foo: 3u8,
384 bar: 4u8
385 },
386 {
387 foo: 5u8,
388 bar: 6u8
389 }
390]";
391 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
392 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
393 assert_eq!(expected, candidate.to_string());
394 assert_eq!("", remainder);
395 }
396
397 #[test]
398 fn test_struct_with_arrays() {
399 let expected = r"{
400 foo: [
401 1u8,
402 2u8,
403 3u8
404 ],
405 bar: [
406 4u8,
407 5u8,
408 6u8
409 ]
410}";
411 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
412 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
413 assert_eq!(expected, candidate.to_string());
414 assert_eq!("", remainder);
415 }
416
417 #[test]
418 fn test_struct_with_array_of_structs() {
419 let expected = r"{
420 foo: [
421 {
422 foo: 1u8,
423 bar: 2u8
424 },
425 {
426 foo: 3u8,
427 bar: 4u8
428 },
429 {
430 foo: 5u8,
431 bar: 6u8
432 }
433 ],
434 bar: [
435 {
436 foo: [
437 1u8,
438 2u8,
439 3u8
440 ],
441 bar: [
442 4u8,
443 5u8,
444 6u8
445 ]
446 },
447 {
448 foo: [
449 7u8,
450 8u8,
451 9u8
452 ],
453 bar: [
454 10u8,
455 11u8,
456 12u8
457 ]
458 },
459 {
460 foo: [
461 13u8,
462 14u8,
463 15u8
464 ],
465 bar: [
466 16u8,
467 17u8,
468 18u8
469 ]
470 }
471 ]
472}";
473 let (remainder, candidate) = Plaintext::<CurrentNetwork>::parse(expected).unwrap();
474 println!("\nExpected: {expected}\n\nFound: {candidate}\n");
475 assert_eq!(expected, candidate.to_string());
476 assert_eq!("", remainder);
477 }
478}