snarkvm_console_program/data/dynamic/record/
parse.rs1use super::*;
17
18impl<N: Network> Parser for DynamicRecord<N> {
19 #[inline]
21 fn parse(string: &str) -> ParserResult<Self> {
22 let (string, _) = Sanitizer::parse(string)?;
24 let (string, _) = tag("{")(string)?;
26
27 let (string, _) = Sanitizer::parse(string)?;
29 let (string, _) = tag("owner")(string)?;
31 let (string, _) = Sanitizer::parse_whitespaces(string)?;
33 let (string, _) = tag(":")(string)?;
35 let (string, _) = Sanitizer::parse(string)?;
37 let (string, owner) = Address::parse(string)?;
39 let (string, _) = tag(",")(string)?;
41
42 let (string, _) = Sanitizer::parse(string)?;
44 let (string, _) = tag("_root")(string)?;
46 let (string, _) = Sanitizer::parse_whitespaces(string)?;
48 let (string, _) = tag(":")(string)?;
50 let (string, _) = Sanitizer::parse(string)?;
52 let (string, root) = Field::parse(string)?;
54 let (string, _) = tag(",")(string)?;
56
57 let (string, _) = Sanitizer::parse(string)?;
59 let (string, _) = tag("_nonce")(string)?;
61 let (string, _) = Sanitizer::parse_whitespaces(string)?;
63 let (string, _) = tag(":")(string)?;
65 let (string, _) = Sanitizer::parse(string)?;
67 let (string, nonce) = Group::parse(string)?;
69
70 let string = match opt(tag(","))(string)? {
72 (string, Some(_)) => string,
74 (string, None) => string,
76 };
77
78 let (string, _) = Sanitizer::parse(string)?;
80 let (string, version) = match opt(tag("_version"))(string)? {
82 (string, None) => (string, U8::zero()),
84 (string, Some(_)) => {
86 let (string, _) = Sanitizer::parse_whitespaces(string)?;
88 let (string, _) = tag(":")(string)?;
90 let (string, _) = Sanitizer::parse(string)?;
92 U8::parse(string)?
94 }
95 };
96
97 let (string, _) = Sanitizer::parse(string)?;
99 let (string, _) = tag("}")(string)?;
101 Ok((string, DynamicRecord::new_unchecked(owner, root, nonce, version, None)))
103 }
104}
105
106impl<N: Network> FromStr for DynamicRecord<N> {
107 type Err = Error;
108
109 fn from_str(string: &str) -> Result<Self> {
111 match Self::parse(string) {
112 Ok((remainder, object)) => {
113 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
115 Ok(object)
117 }
118 Err(error) => bail!("Failed to parse string. {error}"),
119 }
120 }
121}
122
123impl<N: Network> Debug for DynamicRecord<N> {
124 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
126 Display::fmt(self, f)
127 }
128}
129
130impl<N: Network> Display for DynamicRecord<N> {
131 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
133 self.fmt_internal(f, 0)
134 }
135}
136
137impl<N: Network> DynamicRecord<N> {
138 fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result {
140 const INDENT: usize = 2;
142
143 write!(f, "{{")?;
145 write!(f, "\n{:indent$}owner: {},", "", self.owner, indent = (depth + 1) * INDENT)?;
147 write!(f, "\n{:indent$}_root: {},", "", self.root, indent = (depth + 1) * INDENT)?;
149 write!(f, "\n{:indent$}_nonce: {},", "", self.nonce, indent = (depth + 1) * INDENT)?;
151 write!(f, "\n{:indent$}_version: {}", "", self.version, indent = (depth + 1) * INDENT)?;
153 write!(f, "\n{:indent$}}}", "", indent = depth * INDENT)
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::{Entry, Literal, Owner, Record};
162 use snarkvm_console_network::MainnetV0;
163 use snarkvm_console_types::U64;
164 use snarkvm_utilities::{TestRng, Uniform};
165
166 use core::str::FromStr;
167
168 type CurrentNetwork = MainnetV0;
169
170 #[test]
171 fn test_parse_display_roundtrip() {
172 let rng = &mut TestRng::default();
173
174 let data = indexmap::indexmap! {
176 Identifier::from_str("amount").unwrap() => Entry::Private(Plaintext::from(Literal::U64(U64::rand(rng)))),
177 };
178 let owner = Owner::Public(Address::rand(rng));
179 let record = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::from_plaintext(
180 owner,
181 data,
182 Group::rand(rng),
183 U8::new(0),
184 )
185 .unwrap();
186
187 let expected = DynamicRecord::from_record(&record).unwrap();
189
190 let expected_string = expected.to_string();
192
193 let candidate = DynamicRecord::<CurrentNetwork>::from_str(&expected_string).unwrap();
195
196 assert_eq!(expected.owner(), candidate.owner());
198 assert_eq!(expected.root(), candidate.root());
199 assert_eq!(expected.nonce(), candidate.nonce());
200 assert_eq!(expected.version(), candidate.version());
201 }
202
203 #[test]
204 fn test_parse() {
205 let string = "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah, _root: 0field, _nonce: 0group, _version: 0u8 }";
207 let (remainder, candidate) = DynamicRecord::<CurrentNetwork>::parse(string).unwrap();
208 assert!(remainder.is_empty());
209 assert_eq!(
210 *candidate.owner(),
211 Address::from_str("aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah").unwrap()
212 );
213 assert_eq!(*candidate.root(), Field::from_u64(0));
214 assert_eq!(*candidate.nonce(), Group::zero());
215 assert_eq!(*candidate.version(), U8::new(0));
216 }
217
218 #[test]
219 fn test_parse_without_version() {
220 let string = "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah, _root: 123field, _nonce: 0group }";
222 let (remainder, candidate) = DynamicRecord::<CurrentNetwork>::parse(string).unwrap();
223 assert!(remainder.is_empty());
224 assert_eq!(*candidate.version(), U8::new(0));
225 }
226
227 #[test]
228 fn test_display() {
229 let rng = &mut TestRng::default();
230
231 let owner = Owner::Public(Address::rand(rng));
233 let record = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::from_plaintext(
234 owner,
235 indexmap::IndexMap::new(),
236 Group::rand(rng),
237 U8::new(1),
238 )
239 .unwrap();
240
241 let dynamic = DynamicRecord::from_record(&record).unwrap();
243
244 let display = dynamic.to_string();
246 assert!(display.contains("owner:"));
247 assert!(display.contains("_root:"));
248 assert!(display.contains("_nonce:"));
249 assert!(display.contains("_version:"));
250 }
251}