1use crate::values::Value;
18use alloc::vec;
19use core::cmp::Ordering;
20use core::iter::Peekable;
21
22#[macro_export]
54macro_rules! destructure_cbor_map {
55 ( let { $( $key:expr => $variable:ident, )+ } = $map:expr; ) => {
56 #[cfg(test)]
60 $crate::assert_sorted_keys!($( $key, )+);
61
62 use $crate::values::{IntoCborValue, Value};
63 use $crate::macros::destructure_cbor_map_peek_value;
64
65 let mut it = $map.into_iter().peekable();
74 $(
75 let $variable: Option<Value> = destructure_cbor_map_peek_value(&mut it, $key.into_cbor_value());
76 )+
77 };
78}
79
80pub fn destructure_cbor_map_peek_value(
92 it: &mut Peekable<vec::IntoIter<(Value, Value)>>,
93 needle: Value,
94) -> Option<Value> {
95 loop {
96 let item = it.peek()?;
97 let key: &Value = &item.0;
98 match key.cmp(&needle) {
99 Ordering::Less => {
100 it.next();
101 }
102 Ordering::Equal => {
103 let value: Value = it.next().unwrap().1;
104 return Some(value);
105 }
106 Ordering::Greater => return None,
107 }
108 }
109}
110
111#[macro_export]
113macro_rules! assert_sorted_keys {
114 ( $key:expr, ) => {
116 };
117
118 ( $key1:expr, $key2:expr, $( $keys:expr, )* ) => {
119 {
120 use $crate::values::{IntoCborValue, Value};
121 let k1: Value = $key1.into_cbor_value();
122 let k2: Value = $key2.into_cbor_value();
123 assert!(
124 k1 < k2,
125 "{:?} < {:?} failed. The destructure_cbor_map! macro requires keys in sorted order.",
126 k1,
127 k2,
128 );
129 }
130 $crate::assert_sorted_keys!($key2, $( $keys, )*);
131 };
132}
133
134#[macro_export]
155macro_rules! cbor_map {
156 ( $( $key:expr => $value:expr, )+ ) => {
158 cbor_map! ( $($key => $value),+ )
159 };
160
161 ( $( $key:expr => $value:expr ),* ) => {
162 {
163 #[allow(unused_imports)]
165 use $crate::values::IntoCborValue;
166 let mut _map = ::alloc::vec::Vec::new();
167 $(
168 _map.push(($key.into_cbor_value(), $value.into_cbor_value()));
169 )*
170 $crate::values::Value::map(_map)
171 }
172 };
173}
174
175#[macro_export]
196macro_rules! cbor_map_options {
197 ( $( $key:expr => $value:expr, )+ ) => {
199 cbor_map_options! ( $($key => $value),+ )
200 };
201
202 ( $( $key:expr => $value:expr ),* ) => {
203 {
204 #[allow(unused_imports)]
206 use $crate::values::{IntoCborValue, IntoCborValueOption};
207 let mut _map = ::alloc::vec::Vec::<(_, $crate::values::Value)>::new();
208 $(
209 {
210 let opt: Option<$crate::values::Value> = $value.into_cbor_value_option();
211 if let Some(val) = opt {
212 _map.push(($key.into_cbor_value(), val));
213 }
214 }
215 )*
216 $crate::values::Value::map(_map)
217 }
218 };
219}
220
221#[macro_export]
223macro_rules! cbor_map_collection {
224 ( $tree:expr ) => {{ $crate::values::Value::map($tree) }};
225}
226
227#[macro_export]
239macro_rules! cbor_array {
240 ( $( $value:expr, )+ ) => {
242 cbor_array! ( $($value),+ )
243 };
244
245 ( $( $value:expr ),* ) => {
246 {
247 #[allow(unused_imports)]
249 use $crate::values::IntoCborValue;
250 $crate::values::Value::array(vec![ $( $value.into_cbor_value(), )* ])
251 }
252 };
253}
254
255#[macro_export]
257macro_rules! cbor_array_vec {
258 ( $vec:expr ) => {{
259 use $crate::values::IntoCborValue;
260 $crate::values::Value::array($vec.into_iter().map(|x| x.into_cbor_value()).collect())
261 }};
262}
263
264#[macro_export]
266macro_rules! cbor_true {
267 ( ) => {
268 $crate::values::Value::bool_value(true)
269 };
270}
271
272#[macro_export]
274macro_rules! cbor_false {
275 ( ) => {
276 $crate::values::Value::bool_value(false)
277 };
278}
279
280#[macro_export]
282macro_rules! cbor_null {
283 ( ) => {
284 $crate::values::Value::null_value()
285 };
286}
287
288#[macro_export]
290macro_rules! cbor_undefined {
291 ( ) => {
292 $crate::values::Value::undefined()
293 };
294}
295
296#[macro_export]
298macro_rules! cbor_bool {
299 ( $x:expr ) => {
300 $crate::values::Value::bool_value($x)
301 };
302}
303
304#[macro_export]
306macro_rules! cbor_unsigned {
307 ( $x:expr ) => {
308 $crate::values::Value::unsigned($x as u64)
309 };
310}
311
312#[macro_export]
314macro_rules! cbor_int {
315 ( $x:expr ) => {
316 $crate::values::Value::integer($x as i64)
317 };
318}
319
320#[macro_export]
322macro_rules! cbor_text {
323 ( $x:expr ) => {
324 $crate::values::Value::text_string($x.into())
325 };
326}
327
328#[macro_export]
330macro_rules! cbor_bytes {
331 ( $x:expr ) => {
332 $crate::values::Value::byte_string($x)
333 };
334}
335
336#[macro_export]
338macro_rules! cbor_tagged {
339 ( $t:expr, $x: expr ) => {
340 $crate::values::Value::tag($t, $x)
341 };
342}
343
344#[macro_export]
354macro_rules! cbor_bytes_lit {
355 ( $x:expr ) => {
356 $crate::cbor_bytes!(($x as &[u8]).to_vec())
357 };
358}
359
360#[cfg(test)]
361mod test {
362 use super::super::values::Value;
363 use alloc::string::String;
364 use alloc::vec;
365 use alloc::vec::Vec;
366
367 #[test]
368 fn test_cbor_simple_values() {
369 assert_eq!(cbor_true!(), Value::bool_value(true));
370 assert_eq!(cbor_false!(), Value::bool_value(false));
371 assert_eq!(cbor_null!(), Value::null_value());
372 assert_eq!(cbor_undefined!(), Value::undefined());
373 }
374
375 #[test]
376 fn test_cbor_bool() {
377 assert_eq!(cbor_bool!(true), Value::bool_value(true));
378 assert_eq!(cbor_bool!(false), Value::bool_value(false));
379 }
380
381 #[test]
382 fn test_cbor_int_unsigned() {
383 assert_eq!(cbor_int!(0), Value::from(0));
384 assert_eq!(cbor_int!(1), Value::from(1));
385 assert_eq!(cbor_int!(123456), Value::from(123456));
386 assert_eq!(
387 cbor_int!(core::i64::MAX),
388 Value::from(core::i64::MAX as u64)
389 );
390 }
391
392 #[test]
393 fn test_cbor_int_negative() {
394 assert_eq!(cbor_int!(-1), Value::from(-1));
395 assert_eq!(cbor_int!(-123456), Value::from(-123456));
396 assert_eq!(cbor_int!(core::i64::MIN), Value::from(core::i64::MIN));
397 }
398
399 #[test]
400 fn test_cbor_int_literals() {
401 let a = cbor_array![
402 core::i64::MIN,
403 core::i32::MIN,
404 -123456,
405 -1,
406 0,
407 1,
408 123456,
409 core::i32::MAX,
410 core::i64::MAX,
411 core::u64::MAX,
412 ];
413 let b = Value::array(vec![
414 Value::from(core::i64::MIN),
415 Value::from(core::i32::MIN as i64),
416 Value::from(-123456),
417 Value::from(-1),
418 Value::from(0),
419 Value::from(1),
420 Value::from(123456),
421 Value::from(core::i32::MAX as u64),
422 Value::from(core::i64::MAX as u64),
423 Value::from(core::u64::MAX),
424 ]);
425 assert_eq!(a, b);
426 }
427
428 #[test]
429 fn test_cbor_array() {
430 let a = cbor_array![
431 -123,
432 456,
433 true,
434 cbor_null!(),
435 "foo",
436 b"bar",
437 cbor_array![],
438 cbor_array![0, 1],
439 cbor_map! {},
440 cbor_map! {2 => 3},
441 ];
442 let b = Value::array(vec![
443 Value::from(-123),
444 Value::from(456),
445 Value::bool_value(true),
446 Value::null_value(),
447 Value::from(String::from("foo")),
448 Value::from(b"bar".to_vec()),
449 Value::array(Vec::new()),
450 Value::array(vec![Value::from(0), Value::from(1)]),
451 Value::map(Vec::new()),
452 Value::map([(Value::from(2), Value::from(3))].iter().cloned().collect()),
453 ]);
454 assert_eq!(a, b);
455 }
456
457 #[test]
458 fn test_cbor_array_vec_empty() {
459 let a = cbor_array_vec!(Vec::<bool>::new());
460 let b = Value::array(Vec::new());
461 assert_eq!(a, b);
462 }
463
464 #[test]
465 fn test_cbor_array_vec_int() {
466 let a = cbor_array_vec!(vec![1, 2, 3, 4]);
467 let b = Value::array(vec![
468 Value::from(1),
469 Value::from(2),
470 Value::from(3),
471 Value::from(4),
472 ]);
473 assert_eq!(a, b);
474 }
475
476 #[test]
477 fn test_cbor_array_vec_text() {
478 let a = cbor_array_vec!(vec!["a", "b", "c"]);
479 let b = Value::array(vec![
480 Value::from(String::from("a")),
481 Value::from(String::from("b")),
482 Value::from(String::from("c")),
483 ]);
484 assert_eq!(a, b);
485 }
486
487 #[test]
488 fn test_cbor_array_vec_bytes() {
489 let a = cbor_array_vec!(vec![b"a", b"b", b"c"]);
490 let b = Value::array(vec![
491 Value::from(b"a".to_vec()),
492 Value::from(b"b".to_vec()),
493 Value::from(b"c".to_vec()),
494 ]);
495 assert_eq!(a, b);
496 }
497
498 #[test]
499 fn test_cbor_map() {
500 let a = cbor_map! {
501 4 => 56,
502 5 => "foo",
503 6 => b"bar",
504 7 => cbor_array![],
505 8 => cbor_array![0, 1],
506 9 => cbor_map!{},
507 10 => cbor_map!{2 => 3},
508 -1 => -23,
509 b"bar" => cbor_null!(),
510 "foo" => true,
511 };
512 let b = Value::map(
513 [
514 (Value::from(4), Value::from(56)),
515 (Value::from(5), Value::from(String::from("foo"))),
516 (Value::from(6), Value::from(b"bar".to_vec())),
517 (Value::from(7), Value::array(Vec::new())),
518 (
519 Value::from(8),
520 Value::array(vec![Value::from(0), Value::from(1)]),
521 ),
522 (Value::from(9), Value::map(Vec::new())),
523 (
524 Value::from(10),
525 Value::map([(Value::from(2), Value::from(3))].iter().cloned().collect()),
526 ),
527 (Value::from(-1), Value::from(-23)),
528 (Value::from(b"bar".to_vec()), Value::null_value()),
529 (Value::from(String::from("foo")), Value::bool_value(true)),
530 ]
531 .iter()
532 .cloned()
533 .collect(),
534 );
535 assert_eq!(a, b);
536 }
537
538 #[test]
539 fn test_cbor_map_options() {
540 let a = cbor_map_options! {
541 4 => Some(56),
542 5 => "foo",
543 6 => Some(b"bar" as &[u8]),
544 7 => cbor_array![],
545 8 => Some(cbor_array![0, 1]),
546 9 => cbor_map!{},
547 10 => Some(cbor_map!{2 => 3}),
548 11 => None::<String>,
549 12 => None::<&str>,
550 13 => None::<Vec<u8>>,
551 14 => None::<&[u8]>,
552 15 => None::<bool>,
553 16 => None::<i32>,
554 17 => None::<i64>,
555 18 => None::<u64>,
556 -1 => -23,
557 b"bar" => Some(cbor_null!()),
558 "foo" => true,
559 };
560 let b = Value::map(
561 [
562 (Value::from(4), Value::from(56)),
563 (Value::from(5), Value::from(String::from("foo"))),
564 (Value::from(6), Value::from(b"bar".to_vec())),
565 (Value::from(7), Value::array(Vec::new())),
566 (
567 Value::from(8),
568 Value::array(vec![Value::from(0), Value::from(1)]),
569 ),
570 (Value::from(9), Value::map(Vec::new())),
571 (
572 Value::from(10),
573 Value::map([(Value::from(2), Value::from(3))].iter().cloned().collect()),
574 ),
575 (Value::from(-1), Value::from(-23)),
576 (Value::from(b"bar".to_vec()), Value::null_value()),
577 (Value::from(String::from("foo")), Value::bool_value(true)),
578 ]
579 .iter()
580 .cloned()
581 .collect(),
582 );
583 assert_eq!(a, b);
584 }
585
586 #[test]
587 fn test_cbor_map_collection_empty() {
588 let a = cbor_map_collection!(Vec::<(_, _)>::new());
589 let b = Value::map(Vec::new());
590 assert_eq!(a, b);
591 }
592
593 #[test]
594 fn test_cbor_map_collection_foo() {
595 let a = cbor_map_collection!(vec![(Value::from(2), Value::from(3))]);
596 let b = Value::map(vec![(Value::from(2), Value::from(3))]);
597 assert_eq!(a, b);
598 }
599
600 fn extract_map(cbor_value: Value) -> Vec<(Value, Value)> {
601 cbor_value.extract_map().unwrap()
602 }
603
604 #[test]
605 fn test_destructure_cbor_map_simple() {
606 let map = cbor_map! {
607 1 => 10,
608 2 => 20,
609 };
610
611 destructure_cbor_map! {
612 let {
613 1 => x1,
614 2 => x2,
615 } = extract_map(map);
616 }
617
618 assert_eq!(x1, Some(cbor_unsigned!(10)));
619 assert_eq!(x2, Some(cbor_unsigned!(20)));
620 }
621
622 #[test]
623 #[should_panic]
624 fn test_destructure_cbor_map_unsorted() {
625 let map = cbor_map! {
626 1 => 10,
627 2 => 20,
628 };
629
630 destructure_cbor_map! {
631 let {
634 2 => _x2,
635 1 => _x1,
636 } = extract_map(map);
637 }
638 }
639
640 #[test]
641 fn test_destructure_cbor_map_partial() {
642 let map = cbor_map! {
643 1 => 10,
644 2 => 20,
645 3 => 30,
646 4 => 40,
647 5 => 50,
648 6 => 60,
649 7 => 70,
650 8 => 80,
651 9 => 90,
652 };
653
654 destructure_cbor_map! {
655 let {
656 3 => x3,
657 7 => x7,
658 } = extract_map(map);
659 }
660
661 assert_eq!(x3, Some(cbor_unsigned!(30)));
662 assert_eq!(x7, Some(cbor_unsigned!(70)));
663 }
664
665 #[test]
666 fn test_destructure_cbor_map_missing() {
667 let map = cbor_map! {
668 1 => 10,
669 3 => 30,
670 4 => 40,
671 };
672
673 destructure_cbor_map! {
674 let {
675 0 => x0,
676 1 => x1,
677 2 => x2,
678 3 => x3,
679 4 => x4,
680 5 => x5,
681 } = extract_map(map);
682 }
683
684 assert_eq!(x0, None);
685 assert_eq!(x1, Some(cbor_unsigned!(10)));
686 assert_eq!(x2, None);
687 assert_eq!(x3, Some(cbor_unsigned!(30)));
688 assert_eq!(x4, Some(cbor_unsigned!(40)));
689 assert_eq!(x5, None);
690 }
691
692 #[test]
693 fn test_destructure_unsorted_cbor_map() {
694 let map = cbor_map! {
695 2 => 20,
696 1 => 10,
697 };
698
699 destructure_cbor_map! {
700 let {
701 1 => x1,
702 2 => x2,
703 } = extract_map(map);
704 }
705
706 assert_eq!(x1, Some(cbor_unsigned!(10)));
707 assert_eq!(x2, Some(cbor_unsigned!(20)));
708 }
709}