snarkvm_console_program/data/register/
parse.rs

1// Copyright 2024 Aleo Network Foundation
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 Register<N> {
19    /// Parses a string into a register.
20    /// The register is of the form `r{locator}` or `r{locator}.{identifier}`.
21    #[inline]
22    fn parse(string: &str) -> ParserResult<Self> {
23        // Parse the register character from the string.
24        let (string, _) = tag("r")(string)?;
25        // Parse the locator from the string.
26        let (string, locator) =
27            map_res(recognize(many1(one_of("0123456789"))), |locator: &str| locator.parse::<u64>())(string)?;
28        // Parse the accesses from the string, if it is a register access.
29        let (string, accesses): (&str, Vec<Access<N>>) = map_res(many0(Access::parse), |accesses| {
30            // Ensure the number of identifiers is within the limit.
31            if accesses.len() <= N::MAX_DATA_DEPTH {
32                Ok(accesses)
33            } else {
34                Err(error(format!("Register \'r{locator}\' has too many accesses ({})", accesses.len())))
35            }
36        })(string)?;
37        // Return the register.
38        Ok((string, match accesses.len() {
39            0 => Self::Locator(locator),
40            _ => Self::Access(locator, accesses),
41        }))
42    }
43}
44
45impl<N: Network> FromStr for Register<N> {
46    type Err = Error;
47
48    /// Parses a string into a register.
49    #[inline]
50    fn from_str(string: &str) -> Result<Self> {
51        match Self::parse(string) {
52            Ok((remainder, object)) => {
53                // Ensure the remainder is empty.
54                ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
55                // Return the object.
56                Ok(object)
57            }
58            Err(error) => bail!("Failed to parse string. {error}"),
59        }
60    }
61}
62
63impl<N: Network> Debug for Register<N> {
64    /// Prints the register as a string.
65    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
66        Display::fmt(self, f)
67    }
68}
69
70impl<N: Network> Display for Register<N> {
71    /// Prints the register as a string.
72    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
73        match self {
74            // Prints the register, i.e. r0
75            Self::Locator(locator) => write!(f, "r{locator}"),
76            // Prints the register access, i.e. r0.owner
77            Self::Access(locator, accesses) => {
78                write!(f, "r{locator}")?;
79                for access in accesses {
80                    write!(f, "{access}")?;
81                }
82                Ok(())
83            }
84        }
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use crate::{Identifier, U32};
92    use snarkvm_console_network::MainnetV0;
93
94    type CurrentNetwork = MainnetV0;
95    #[test]
96    fn test_register_display() -> Result<()> {
97        // Register::Locator
98        assert_eq!("r0", Register::<CurrentNetwork>::Locator(0).to_string());
99        assert_eq!("r1", Register::<CurrentNetwork>::Locator(1).to_string());
100        assert_eq!("r2", Register::<CurrentNetwork>::Locator(2).to_string());
101        assert_eq!("r3", Register::<CurrentNetwork>::Locator(3).to_string());
102        assert_eq!("r4", Register::<CurrentNetwork>::Locator(4).to_string());
103
104        // Register::Access with Access::Member
105        assert_eq!(
106            "r0.owner",
107            Register::<CurrentNetwork>::Access(0, vec![Access::Member(Identifier::from_str("owner")?)]).to_string()
108        );
109        assert_eq!(
110            "r1.owner",
111            Register::<CurrentNetwork>::Access(1, vec![Access::Member(Identifier::from_str("owner")?)]).to_string()
112        );
113        assert_eq!(
114            "r2.owner",
115            Register::<CurrentNetwork>::Access(2, vec![Access::Member(Identifier::from_str("owner")?)]).to_string()
116        );
117        assert_eq!(
118            "r3.owner",
119            Register::<CurrentNetwork>::Access(3, vec![Access::Member(Identifier::from_str("owner")?)]).to_string()
120        );
121        assert_eq!(
122            "r4.owner",
123            Register::<CurrentNetwork>::Access(4, vec![Access::Member(Identifier::from_str("owner")?)]).to_string()
124        );
125
126        // Register::Access with Access::Index
127        assert_eq!("r0[0u32]", Register::<CurrentNetwork>::Access(0, vec![Access::Index(U32::new(0))]).to_string());
128        assert_eq!(
129            "r1[0u32][1u32]",
130            Register::<CurrentNetwork>::Access(1, vec![Access::Index(U32::new(0)), Access::Index(U32::new(1))])
131                .to_string()
132        );
133        assert_eq!(
134            "r2[0u32][1u32][2u32]",
135            Register::<CurrentNetwork>::Access(2, vec![
136                Access::Index(U32::new(0)),
137                Access::Index(U32::new(1)),
138                Access::Index(U32::new(2))
139            ])
140            .to_string()
141        );
142        assert_eq!(
143            "r3[0u32][1u32][2u32][3u32]",
144            Register::<CurrentNetwork>::Access(3, vec![
145                Access::Index(U32::new(0)),
146                Access::Index(U32::new(1)),
147                Access::Index(U32::new(2)),
148                Access::Index(U32::new(3))
149            ])
150            .to_string()
151        );
152        assert_eq!(
153            "r4[0u32][1u32][2u32][3u32][4u32]",
154            Register::<CurrentNetwork>::Access(4, vec![
155                Access::Index(U32::new(0)),
156                Access::Index(U32::new(1)),
157                Access::Index(U32::new(2)),
158                Access::Index(U32::new(3)),
159                Access::Index(U32::new(4))
160            ])
161            .to_string()
162        );
163
164        // Register::Access with Access::Member and Access::Index
165        assert_eq!(
166            "r0.owner[0u32]",
167            Register::<CurrentNetwork>::Access(0, vec![
168                Access::Member(Identifier::from_str("owner")?),
169                Access::Index(U32::new(0))
170            ])
171            .to_string()
172        );
173        assert_eq!(
174            "r1.owner[0u32].owner",
175            Register::<CurrentNetwork>::Access(1, vec![
176                Access::Member(Identifier::from_str("owner")?),
177                Access::Index(U32::new(0)),
178                Access::Member(Identifier::from_str("owner")?)
179            ])
180            .to_string()
181        );
182        assert_eq!(
183            "r2.owner[0u32].owner[1u32]",
184            Register::<CurrentNetwork>::Access(2, vec![
185                Access::Member(Identifier::from_str("owner")?),
186                Access::Index(U32::new(0)),
187                Access::Member(Identifier::from_str("owner")?),
188                Access::Index(U32::new(1))
189            ])
190            .to_string()
191        );
192        assert_eq!(
193            "r3.owner[0u32].owner[1u32].owner",
194            Register::<CurrentNetwork>::Access(3, vec![
195                Access::Member(Identifier::from_str("owner")?),
196                Access::Index(U32::new(0)),
197                Access::Member(Identifier::from_str("owner")?),
198                Access::Index(U32::new(1)),
199                Access::Member(Identifier::from_str("owner")?)
200            ])
201            .to_string()
202        );
203        assert_eq!(
204            "r4.owner[0u32].owner[1u32].owner[2u32]",
205            Register::<CurrentNetwork>::Access(4, vec![
206                Access::Member(Identifier::from_str("owner")?),
207                Access::Index(U32::new(0)),
208                Access::Member(Identifier::from_str("owner")?),
209                Access::Index(U32::new(1)),
210                Access::Member(Identifier::from_str("owner")?),
211                Access::Index(U32::new(2))
212            ])
213            .to_string()
214        );
215
216        Ok(())
217    }
218
219    #[test]
220    fn test_register_to_string() -> Result<()> {
221        // Register::Locator
222        assert_eq!(Register::<CurrentNetwork>::Locator(0).to_string(), "r0".to_string());
223        assert_eq!(Register::<CurrentNetwork>::Locator(1).to_string(), "r1".to_string());
224        assert_eq!(Register::<CurrentNetwork>::Locator(2).to_string(), "r2".to_string());
225        assert_eq!(Register::<CurrentNetwork>::Locator(3).to_string(), "r3".to_string());
226        assert_eq!(Register::<CurrentNetwork>::Locator(4).to_string(), "r4".to_string());
227
228        // Register::Access with Access::Member
229        assert_eq!(
230            Register::<CurrentNetwork>::Access(0, vec![Access::Member(Identifier::from_str("owner")?)]).to_string(),
231            "r0.owner".to_string()
232        );
233        assert_eq!(
234            Register::<CurrentNetwork>::Access(1, vec![Access::Member(Identifier::from_str("owner")?)]).to_string(),
235            "r1.owner".to_string()
236        );
237        assert_eq!(
238            Register::<CurrentNetwork>::Access(2, vec![Access::Member(Identifier::from_str("owner")?)]).to_string(),
239            "r2.owner".to_string()
240        );
241        assert_eq!(
242            Register::<CurrentNetwork>::Access(3, vec![Access::Member(Identifier::from_str("owner")?)]).to_string(),
243            "r3.owner".to_string()
244        );
245        assert_eq!(
246            Register::<CurrentNetwork>::Access(4, vec![Access::Member(Identifier::from_str("owner")?)]).to_string(),
247            "r4.owner".to_string()
248        );
249
250        // Register::Access with Access::Index
251        assert_eq!(
252            Register::<CurrentNetwork>::Access(0, vec![Access::Index(U32::new(0))]).to_string(),
253            "r0[0u32]".to_string()
254        );
255        assert_eq!(
256            Register::<CurrentNetwork>::Access(1, vec![Access::Index(U32::new(0)), Access::Index(U32::new(1))])
257                .to_string(),
258            "r1[0u32][1u32]".to_string()
259        );
260        assert_eq!(
261            Register::<CurrentNetwork>::Access(2, vec![
262                Access::Index(U32::new(0)),
263                Access::Index(U32::new(1)),
264                Access::Index(U32::new(2))
265            ])
266            .to_string(),
267            "r2[0u32][1u32][2u32]".to_string()
268        );
269        assert_eq!(
270            Register::<CurrentNetwork>::Access(3, vec![
271                Access::Index(U32::new(0)),
272                Access::Index(U32::new(1)),
273                Access::Index(U32::new(2)),
274                Access::Index(U32::new(3))
275            ])
276            .to_string(),
277            "r3[0u32][1u32][2u32][3u32]".to_string()
278        );
279        assert_eq!(
280            Register::<CurrentNetwork>::Access(4, vec![
281                Access::Index(U32::new(0)),
282                Access::Index(U32::new(1)),
283                Access::Index(U32::new(2)),
284                Access::Index(U32::new(3)),
285                Access::Index(U32::new(4))
286            ])
287            .to_string(),
288            "r4[0u32][1u32][2u32][3u32][4u32]".to_string()
289        );
290
291        // Register::Access with Access::Member and Access::Index
292        assert_eq!(
293            Register::<CurrentNetwork>::Access(0, vec![
294                Access::Member(Identifier::from_str("owner")?),
295                Access::Index(U32::new(0))
296            ])
297            .to_string(),
298            "r0.owner[0u32]".to_string()
299        );
300        assert_eq!(
301            Register::<CurrentNetwork>::Access(1, vec![
302                Access::Member(Identifier::from_str("owner")?),
303                Access::Index(U32::new(0)),
304                Access::Member(Identifier::from_str("owner")?)
305            ])
306            .to_string(),
307            "r1.owner[0u32].owner".to_string()
308        );
309        assert_eq!(
310            Register::<CurrentNetwork>::Access(2, vec![
311                Access::Member(Identifier::from_str("owner")?),
312                Access::Index(U32::new(0)),
313                Access::Member(Identifier::from_str("owner")?),
314                Access::Index(U32::new(1))
315            ])
316            .to_string(),
317            "r2.owner[0u32].owner[1u32]".to_string()
318        );
319        assert_eq!(
320            Register::<CurrentNetwork>::Access(3, vec![
321                Access::Member(Identifier::from_str("owner")?),
322                Access::Index(U32::new(0)),
323                Access::Member(Identifier::from_str("owner")?),
324                Access::Index(U32::new(1)),
325                Access::Member(Identifier::from_str("owner")?)
326            ])
327            .to_string(),
328            "r3.owner[0u32].owner[1u32].owner".to_string()
329        );
330        assert_eq!(
331            Register::<CurrentNetwork>::Access(4, vec![
332                Access::Member(Identifier::from_str("owner")?),
333                Access::Index(U32::new(0)),
334                Access::Member(Identifier::from_str("owner")?),
335                Access::Index(U32::new(1)),
336                Access::Member(Identifier::from_str("owner")?),
337                Access::Index(U32::new(2))
338            ])
339            .to_string(),
340            "r4.owner[0u32].owner[1u32].owner[2u32]".to_string()
341        );
342
343        Ok(())
344    }
345
346    #[test]
347    fn test_register_parse() -> Result<()> {
348        // Register::Locator
349        assert_eq!(("", Register::<CurrentNetwork>::Locator(0)), Register::parse("r0").unwrap());
350        assert_eq!(("", Register::<CurrentNetwork>::Locator(1)), Register::parse("r1").unwrap());
351        assert_eq!(("", Register::<CurrentNetwork>::Locator(2)), Register::parse("r2").unwrap());
352        assert_eq!(("", Register::<CurrentNetwork>::Locator(3)), Register::parse("r3").unwrap());
353        assert_eq!(("", Register::<CurrentNetwork>::Locator(4)), Register::parse("r4").unwrap());
354
355        // Register::Access with Access::Member
356        assert_eq!(
357            ("", Register::<CurrentNetwork>::Access(0, vec![Access::Member(Identifier::from_str("owner")?)])),
358            Register::parse("r0.owner").unwrap()
359        );
360        assert_eq!(
361            ("", Register::<CurrentNetwork>::Access(1, vec![Access::Member(Identifier::from_str("owner")?)])),
362            Register::parse("r1.owner").unwrap()
363        );
364        assert_eq!(
365            ("", Register::<CurrentNetwork>::Access(2, vec![Access::Member(Identifier::from_str("owner")?)])),
366            Register::parse("r2.owner").unwrap()
367        );
368        assert_eq!(
369            ("", Register::<CurrentNetwork>::Access(3, vec![Access::Member(Identifier::from_str("owner")?)])),
370            Register::parse("r3.owner").unwrap()
371        );
372        assert_eq!(
373            ("", Register::<CurrentNetwork>::Access(4, vec![Access::Member(Identifier::from_str("owner")?)])),
374            Register::parse("r4.owner").unwrap()
375        );
376
377        for i in 1..=CurrentNetwork::MAX_DATA_DEPTH {
378            let mut string = "r0".to_string();
379            for _ in 0..i {
380                string.push_str(".owner");
381            }
382
383            assert_eq!(
384                ("", Register::<CurrentNetwork>::Access(0, vec![Access::Member(Identifier::from_str("owner")?); i])),
385                Register::<CurrentNetwork>::parse(&string).unwrap()
386            );
387        }
388
389        // Register::Access with Access::Index
390        assert_eq!(
391            ("", Register::<CurrentNetwork>::Access(0, vec![Access::Index(U32::new(0))])),
392            Register::parse("r0[0u32]").unwrap()
393        );
394        assert_eq!(
395            ("", Register::<CurrentNetwork>::Access(1, vec![Access::Index(U32::new(0))])),
396            Register::parse("r1[0u32]").unwrap()
397        );
398        assert_eq!(
399            ("", Register::<CurrentNetwork>::Access(2, vec![Access::Index(U32::new(0))])),
400            Register::parse("r2[0u32]").unwrap()
401        );
402        assert_eq!(
403            ("", Register::<CurrentNetwork>::Access(3, vec![Access::Index(U32::new(0))])),
404            Register::parse("r3[0u32]").unwrap()
405        );
406        assert_eq!(
407            ("", Register::<CurrentNetwork>::Access(4, vec![Access::Index(U32::new(0))])),
408            Register::parse("r4[0u32]").unwrap()
409        );
410
411        for i in 1..=CurrentNetwork::MAX_DATA_DEPTH {
412            let mut string = "r0".to_string();
413            for _ in 0..i {
414                string.push_str("[0u32]");
415            }
416
417            assert_eq!(
418                ("", Register::<CurrentNetwork>::Access(0, vec![Access::Index(U32::new(0)); i])),
419                Register::<CurrentNetwork>::parse(&string).unwrap()
420            );
421        }
422
423        // Register::Access with Access::Member and Access::Index
424        assert_eq!(
425            (
426                "",
427                Register::<CurrentNetwork>::Access(0, vec![
428                    Access::Member(Identifier::from_str("owner")?),
429                    Access::Index(U32::new(0))
430                ])
431            ),
432            Register::parse("r0.owner[0u32]").unwrap()
433        );
434        assert_eq!(
435            (
436                "",
437                Register::<CurrentNetwork>::Access(1, vec![
438                    Access::Member(Identifier::from_str("owner")?),
439                    Access::Index(U32::new(0)),
440                    Access::Member(Identifier::from_str("owner")?)
441                ])
442            ),
443            Register::parse("r1.owner[0u32].owner").unwrap()
444        );
445        assert_eq!(
446            (
447                "",
448                Register::<CurrentNetwork>::Access(2, vec![
449                    Access::Member(Identifier::from_str("owner")?),
450                    Access::Index(U32::new(0)),
451                    Access::Member(Identifier::from_str("owner")?),
452                    Access::Index(U32::new(0))
453                ])
454            ),
455            Register::parse("r2.owner[0u32].owner[0u32]").unwrap()
456        );
457        assert_eq!(
458            (
459                "",
460                Register::<CurrentNetwork>::Access(3, vec![
461                    Access::Member(Identifier::from_str("owner")?),
462                    Access::Index(U32::new(0)),
463                    Access::Member(Identifier::from_str("owner")?),
464                    Access::Index(U32::new(0)),
465                    Access::Member(Identifier::from_str("owner")?)
466                ])
467            ),
468            Register::parse("r3.owner[0u32].owner[0u32].owner").unwrap()
469        );
470        assert_eq!(
471            (
472                "",
473                Register::<CurrentNetwork>::Access(4, vec![
474                    Access::Member(Identifier::from_str("owner")?),
475                    Access::Index(U32::new(0)),
476                    Access::Member(Identifier::from_str("owner")?),
477                    Access::Index(U32::new(0)),
478                    Access::Member(Identifier::from_str("owner")?),
479                    Access::Index(U32::new(0))
480                ])
481            ),
482            Register::parse("r4.owner[0u32].owner[0u32].owner[0u32]").unwrap()
483        );
484
485        Ok(())
486    }
487
488    #[test]
489    fn test_register_parser_fails() {
490        assert!(Register::<CurrentNetwork>::parse("").is_err());
491        assert!(Register::<CurrentNetwork>::parse("r").is_err());
492
493        // Register::Access with multiple identifiers that exceed the maximum depth.
494        for i in CurrentNetwork::MAX_DATA_DEPTH + 1..CurrentNetwork::MAX_DATA_DEPTH * 2 {
495            let mut string = "r0".to_string();
496            for _ in 0..i {
497                string.push_str(".owner");
498            }
499
500            assert!(Register::<CurrentNetwork>::parse(&string).is_err());
501        }
502
503        // Register::Access with multiple indices that exceed the maximum depth.
504        for i in CurrentNetwork::MAX_DATA_DEPTH + 1..CurrentNetwork::MAX_DATA_DEPTH * 2 {
505            let mut string = "r0".to_string();
506            for _ in 0..i {
507                string.push_str("[0u32]");
508            }
509
510            assert!(Register::<CurrentNetwork>::parse(&string).is_err());
511        }
512
513        // Register::Access with multiple indices and members that exceed the maximum depth.
514        for i in CurrentNetwork::MAX_DATA_DEPTH + 1..CurrentNetwork::MAX_DATA_DEPTH * 2 {
515            let mut string = "r0".to_string();
516            for n in 0..i {
517                if n % 2 == 0 {
518                    string.push_str("[0u32]");
519                } else {
520                    string.push_str(".owner");
521                }
522            }
523
524            assert!(Register::<CurrentNetwork>::parse(&string).is_err());
525        }
526    }
527}