1#[macro_export]
56macro_rules! get_path {
57 (@access $root:ident,) => {};
58 (@access $root:ident, !) => {
59 let $root = $root.unwrap();
60 };
61 (@access $root:ident, . $field:ident $( $tail:tt )*) => {
62 let $root = $root.and_then(|a| a.value()).map(|v| &v.$field);
63 get_path!(@access $root, $($tail)*);
64 };
65 (@access $root:ident, [ $index:literal ] $( $tail:tt )*) => {
66 let $root = $root.and_then(|a| a.value()).and_then(|v| v.get($index));
67 get_path!(@access $root, $($tail)*);
68 };
69 ($root:ident $( $tail:tt )*) => {{
70 let $root = Some(&$root);
71 $crate::get_path!(@access $root, $($tail)*);
72 $root
73 }};
74}
75
76#[macro_export]
129macro_rules! get_value {
130 (@access $root:ident,) => {};
131 (@access $root:ident, !) => {
132 let $root = $root.unwrap();
133 };
134 (@access $root:ident, . $field:ident $( $tail:tt )*) => {
135 let $root = $root.and_then(|v| v.$field.value());
136 get_value!(@access $root, $($tail)*);
137 };
138 (@access $root:ident, [ $index:literal ] $( $tail:tt )*) => {
139 let $root = $root.and_then(|v| v.get($index)).and_then(|a| a.value());
140 get_value!(@access $root, $($tail)*);
141 };
142 ($root:ident $( $tail:tt )*) => {{
143 let $root = $root.value();
144 $crate::get_value!(@access $root, $($tail)*);
145 $root
146 }};
147}
148
149#[macro_export]
162macro_rules! derive_string_meta_structure {
163 ($type:ident, $expectation:expr) => {
164 impl $crate::FromValue for $type {
165 fn from_value(value: Annotated<Value>) -> Annotated<Self> {
166 match value {
167 Annotated(Some(Value::String(value)), mut meta) => match value.parse() {
168 Ok(value) => Annotated(Some(value), meta),
169 Err(err) => {
170 meta.add_error($crate::Error::invalid(err));
171 meta.set_original_value(Some(value));
172 Annotated(None, meta)
173 }
174 },
175 Annotated(None, meta) => Annotated(None, meta),
176 Annotated(Some(value), mut meta) => {
177 meta.add_error($crate::Error::expected($expectation));
178 meta.set_original_value(Some(value));
179 Annotated(None, meta)
180 }
181 }
182 }
183 }
184
185 impl $crate::IntoValue for $type {
186 fn into_value(self) -> Value {
187 Value::String(self.to_string())
188 }
189
190 fn serialize_payload<S>(
191 &self,
192 s: S,
193 _behavior: $crate::SkipSerialization,
194 ) -> Result<S::Ok, S::Error>
195 where
196 Self: Sized,
197 S: serde::ser::Serializer,
198 {
199 s.collect_str(self)
200 }
201 }
202
203 impl $crate::Empty for $type {
204 fn is_empty(&self) -> bool {
205 false
206 }
207 }
208 };
209}
210
211pub use derive_string_meta_structure;
212
213#[cfg(feature = "test")]
215#[macro_export]
216macro_rules! assert_annotated_snapshot {
217 ($value:expr, @$snapshot:literal) => {
218 ::insta::assert_snapshot!(
219 $value.to_json_pretty().unwrap(),
220 stringify!($value),
221 @$snapshot
222 )
223 };
224 ($value:expr, $debug_expr:expr, @$snapshot:literal) => {
225 ::insta::assert_snapshot!(
226 $value.to_json_pretty().unwrap(),
227 $debug_expr,
228 @$snapshot
229 )
230 };
231 ($name:expr, $value:expr) => {
232 ::insta::assert_snapshot!(
233 $name,
234 $value.to_json_pretty().unwrap(),
235 stringify!($value)
236 )
237 };
238 ($name:expr, $value:expr, $debug_expr:expr) => {
239 ::insta::assert_snapshot!(
240 $name,
241 $value.to_json_pretty().unwrap(),
242 $debug_expr
243 )
244 };
245 ($value:expr) => {
246 ::insta::assert_snapshot!(
247 None::<String>,
248 $value.to_json_pretty().unwrap(),
249 stringify!($value)
250 )
251 };
252}
253
254#[cfg(test)]
255mod tests {
256 use similar_asserts::assert_eq;
257
258 use crate::{Annotated, Array, Object};
259
260 #[derive(Clone, Debug, PartialEq)]
261 struct Inner {
262 value: Annotated<u64>,
263 }
264
265 #[derive(Clone, Debug, PartialEq)]
266 struct Outer {
267 inner: Annotated<Inner>,
268 }
269
270 #[test]
271 fn get_path() {
272 let value = Annotated::new(1);
273 let inner = Annotated::new(Inner {
274 value: value.clone(),
275 });
276 let outer = Annotated::new(Outer {
277 inner: inner.clone(),
278 });
279
280 assert_eq!(get_path!(outer), Some(&outer));
282 assert_eq!(get_path!(outer.inner), Some(&inner));
283 assert_eq!(get_path!(outer.inner.value), Some(&value));
284
285 assert_eq!(get_path!(outer!), &outer);
287 assert_eq!(get_path!(outer.inner!), &inner);
288 assert_eq!(get_path!(outer.inner.value!), &value);
289 }
290
291 #[test]
292 fn get_path_empty() {
293 let empty = Annotated::<Outer>::empty();
294 let outer_empty = Annotated::new(Outer {
295 inner: Annotated::empty(),
296 });
297 let outer = Annotated::new(Outer {
298 inner: Annotated::new(Inner {
299 value: Annotated::empty(),
300 }),
301 });
302
303 assert_eq!(get_path!(empty), Some(&Annotated::empty()));
305 assert_eq!(get_path!(outer_empty.inner), Some(&Annotated::empty()));
306 assert_eq!(get_path!(outer.inner.value), Some(&Annotated::empty()));
307
308 assert_eq!(get_path!(empty.inner), None);
310 assert_eq!(get_path!(empty.inner.value), None);
311 assert_eq!(get_path!(outer_empty.inner.value), None);
312
313 assert_eq!(get_path!(empty!), &Annotated::empty());
315 assert_eq!(get_path!(outer_empty.inner!), &Annotated::empty());
316 assert_eq!(get_path!(outer.inner.value!), &Annotated::empty());
317 }
318
319 #[test]
320 fn get_path_array() {
321 let array = Annotated::new(Array::from([Annotated::new(0), Annotated::new(1)]));
322
323 assert_eq!(get_path!(array[0]), Some(&Annotated::new(0)));
325 assert_eq!(get_path!(array[1]), Some(&Annotated::new(1)));
326 assert_eq!(get_path!(array[2]), None);
328 assert_eq!(get_path!(array[0]!), &Annotated::new(0));
330 }
331
332 #[test]
333 fn get_path_object() {
334 let object = Annotated::new(Object::from([("key".to_string(), Annotated::new(1))]));
335
336 assert_eq!(get_path!(object["key"]), Some(&Annotated::new(1)));
338 assert_eq!(get_path!(object["key"]!), &Annotated::new(1));
340 assert_eq!(get_path!(object["other"]), None);
342 }
343
344 #[test]
345 fn get_path_combined() {
346 struct Inner {
347 value: Annotated<u64>,
348 }
349
350 struct Outer {
351 inners: Annotated<Object<Inner>>,
352 }
353
354 let outer = Annotated::new(Outer {
355 inners: Annotated::new(Object::from([(
356 "key".to_string(),
357 Annotated::new(Inner {
358 value: Annotated::new(1),
359 }),
360 )])),
361 });
362
363 assert_eq!(
364 get_path!(outer.inners["key"].value),
365 Some(&Annotated::new(1))
366 );
367 assert_eq!(get_path!(outer.inners["key"].value!), &Annotated::new(1));
368 }
369
370 #[test]
371 fn get_value() {
372 let inner = Inner {
373 value: Annotated::new(1),
374 };
375 let outer = Outer {
376 inner: Annotated::new(inner.clone()),
377 };
378 let annotated = Annotated::new(outer.clone());
379
380 assert_eq!(get_value!(annotated), Some(&outer));
382 assert_eq!(get_value!(annotated.inner), Some(&inner));
383 assert_eq!(get_value!(annotated.inner.value), Some(&1));
384
385 assert_eq!(get_value!(annotated!), &outer);
387 assert_eq!(get_value!(annotated.inner!), &inner);
388 assert_eq!(get_value!(annotated.inner.value!), &1);
389 }
390
391 #[test]
392 fn get_value_empty() {
393 let empty = Annotated::<Outer>::empty();
394 let outer_empty = Annotated::new(Outer {
395 inner: Annotated::empty(),
396 });
397 let outer = Annotated::new(Outer {
398 inner: Annotated::new(Inner {
399 value: Annotated::empty(),
400 }),
401 });
402
403 assert_eq!(get_value!(empty), None);
405 assert_eq!(get_value!(outer_empty.inner), None);
406 assert_eq!(get_value!(outer.inner.value), None);
407
408 assert_eq!(get_value!(empty.inner), None);
410 assert_eq!(get_value!(empty.inner.value), None);
411 assert_eq!(get_value!(outer_empty.inner.value), None);
412 }
413
414 #[test]
415 fn get_value_array() {
416 let array = Annotated::new(Array::from([Annotated::new(0), Annotated::new(1)]));
417
418 assert_eq!(get_value!(array[0]), Some(&0));
420 assert_eq!(get_value!(array[1]), Some(&1));
421 assert_eq!(get_value!(array[2]), None);
423 assert_eq!(get_value!(array[0]!), &0);
425 }
426
427 #[test]
428 fn get_value_object() {
429 let object = Annotated::new(Object::from([("key".to_string(), Annotated::new(1))]));
430
431 assert_eq!(get_value!(object["key"]), Some(&1));
433 assert_eq!(get_value!(object["key"]!), &1);
435 assert_eq!(get_value!(object["other"]), None);
437 }
438
439 #[test]
440 fn get_value_combined() {
441 struct Inner {
442 value: Annotated<u64>,
443 }
444
445 struct Outer {
446 inners: Annotated<Object<Inner>>,
447 }
448
449 let outer = Annotated::new(Outer {
450 inners: Annotated::new(Object::from([(
451 "key".to_string(),
452 Annotated::new(Inner {
453 value: Annotated::new(1),
454 }),
455 )])),
456 });
457
458 assert_eq!(get_value!(outer.inners["key"].value), Some(&1));
459 assert_eq!(get_value!(outer.inners["key"].value!), &1);
460 }
461}