1use core::cmp::Ordering;
12
13use crate::canonical::CanonicalCborRef;
14use crate::profile::{checked_text_len, cmp_text_keys_canonical};
15use crate::utf8;
16use crate::wire;
17use crate::{CborError, ErrorCode};
18
19#[cfg(feature = "alloc")]
20use crate::canonical::CanonicalCbor;
21#[cfg(feature = "alloc")]
22use crate::canonical::EncodedTextKey;
23
24#[cfg(feature = "alloc")]
25use alloc::vec::Vec;
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum CborKind {
30 Integer,
32 Bytes,
34 Text,
36 Array,
38 Map,
40 Bool,
42 Null,
44 Float,
46}
47
48const fn err(code: ErrorCode, offset: usize) -> CborError {
49 CborError::new(code, offset)
50}
51
52const fn malformed(offset: usize) -> CborError {
53 err(ErrorCode::MalformedCanonical, offset)
54}
55
56const fn expected_map(offset: usize) -> CborError {
57 err(ErrorCode::ExpectedMap, offset)
58}
59
60const fn expected_array(offset: usize) -> CborError {
61 err(ErrorCode::ExpectedArray, offset)
62}
63
64const fn expected_integer(offset: usize) -> CborError {
65 err(ErrorCode::ExpectedInteger, offset)
66}
67
68const fn expected_text(offset: usize) -> CborError {
69 err(ErrorCode::ExpectedText, offset)
70}
71
72const fn expected_bytes(offset: usize) -> CborError {
73 err(ErrorCode::ExpectedBytes, offset)
74}
75
76const fn expected_bool(offset: usize) -> CborError {
77 err(ErrorCode::ExpectedBool, offset)
78}
79
80const fn expected_float(offset: usize) -> CborError {
81 err(ErrorCode::ExpectedFloat, offset)
82}
83
84const fn missing_key(offset: usize) -> CborError {
85 err(ErrorCode::MissingKey, offset)
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub enum PathElem<'p> {
93 Key(&'p str),
95 Index(usize),
97}
98
99impl<'p> From<&'p str> for PathElem<'p> {
100 fn from(key: &'p str) -> Self {
101 Self::Key(key)
102 }
103}
104
105impl From<usize> for PathElem<'_> {
106 fn from(index: usize) -> Self {
107 Self::Index(index)
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113pub struct BigIntRef<'a> {
114 negative: bool,
115 magnitude: &'a [u8],
116}
117
118impl<'a> BigIntRef<'a> {
119 #[must_use]
121 pub const fn is_negative(self) -> bool {
122 self.negative
123 }
124
125 #[must_use]
127 pub const fn magnitude(self) -> &'a [u8] {
128 self.magnitude
129 }
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum CborIntegerRef<'a> {
135 Safe(i64),
137 Big(BigIntRef<'a>),
139}
140
141impl<'a> CborIntegerRef<'a> {
142 #[must_use]
144 pub const fn as_i64(self) -> Option<i64> {
145 match self {
146 Self::Safe(v) => Some(v),
147 Self::Big(_) => None,
148 }
149 }
150
151 #[must_use]
153 pub const fn as_bigint(self) -> Option<BigIntRef<'a>> {
154 match self {
155 Self::Safe(_) => None,
156 Self::Big(b) => Some(b),
157 }
158 }
159}
160
161#[derive(Debug, Clone, Copy)]
167pub struct CborValueRef<'a> {
168 data: &'a [u8],
169 start: usize,
170 end: usize,
171}
172
173#[allow(clippy::elidable_lifetime_names)]
174impl<'a> CborValueRef<'a> {
175 #[inline]
176 pub(crate) const fn new(data: &'a [u8], start: usize, end: usize) -> Self {
177 Self { data, start, end }
178 }
179
180 #[cfg(feature = "unsafe")]
186 #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
187 #[inline]
188 #[must_use]
189 pub unsafe fn from_canonical_range(data: &'a [u8], start: usize, end: usize) -> Self {
190 debug_assert!(start <= end && end <= data.len());
191 Self { data, start, end }
192 }
193
194 #[must_use]
196 pub fn as_bytes(self) -> &'a [u8] {
197 &self.data[self.start..self.end]
199 }
200
201 #[must_use]
203 pub const fn offset(self) -> usize {
204 self.start
205 }
206
207 #[must_use]
209 pub const fn len(self) -> usize {
210 self.end.saturating_sub(self.start)
211 }
212
213 #[must_use]
215 pub const fn is_empty(self) -> bool {
216 self.start >= self.end
217 }
218
219 pub fn kind(self) -> Result<CborKind, CborError> {
225 let mut pos = self.start;
226 let off = self.start;
227 let ib = read_u8_trusted(self.data, &mut pos)?;
228 let major = ib >> 5;
229 let ai = ib & 0x1f;
230
231 match major {
232 0 | 1 => Ok(CborKind::Integer),
233 2 => Ok(CborKind::Bytes),
234 3 => Ok(CborKind::Text),
235 4 => Ok(CborKind::Array),
236 5 => Ok(CborKind::Map),
237 6 => {
238 let tag = read_uint_trusted(self.data, &mut pos, ai, off)?;
239 match tag {
240 2 | 3 => Ok(CborKind::Integer),
241 _ => Err(malformed(off)),
242 }
243 }
244 7 => match ai {
245 20 | 21 => Ok(CborKind::Bool),
246 22 => Ok(CborKind::Null),
247 27 => Ok(CborKind::Float),
248 _ => Err(malformed(off)),
249 },
250 _ => Err(malformed(off)),
251 }
252 }
253
254 #[must_use]
256 pub fn is_null(self) -> bool {
257 self.data.get(self.start) == Some(&0xf6)
258 }
259
260 pub fn map(self) -> Result<MapRef<'a>, CborError> {
266 let (len, entries_start) = parse_map_header(self.data, self.start)?;
267 Ok(MapRef {
268 data: self.data,
269 map_off: self.start,
270 entries_start,
271 len,
272 })
273 }
274
275 pub fn array(self) -> Result<ArrayRef<'a>, CborError> {
281 let (len, items_start) = parse_array_header(self.data, self.start)?;
282 Ok(ArrayRef {
283 data: self.data,
284 array_off: self.start,
285 items_start,
286 len,
287 })
288 }
289
290 pub fn get_key(self, key: &str) -> Result<Option<Self>, CborError> {
296 self.map()?.get(key)
297 }
298
299 pub fn get_index(self, index: usize) -> Result<Option<Self>, CborError> {
305 self.array()?.get(index)
306 }
307
308 pub fn at(self, path: &[PathElem<'_>]) -> Result<Option<Self>, CborError> {
317 let mut cur = self;
318 for pe in path {
319 match *pe {
320 PathElem::Key(k) => match cur.get_key(k)? {
321 Some(v) => cur = v,
322 None => return Ok(None),
323 },
324 PathElem::Index(i) => match cur.get_index(i)? {
325 Some(v) => cur = v,
326 None => return Ok(None),
327 },
328 }
329 }
330 Ok(Some(cur))
331 }
332
333 pub fn integer(self) -> Result<CborIntegerRef<'a>, CborError> {
339 let mut pos = self.start;
340 let off = self.start;
341 let ib = read_u8_trusted(self.data, &mut pos)?;
342 let major = ib >> 5;
343 let ai = ib & 0x1f;
344
345 match major {
346 0 => {
347 let u = read_uint_trusted(self.data, &mut pos, ai, off)?;
348 let i = i64::try_from(u).map_err(|_| malformed(off))?;
349 Ok(CborIntegerRef::Safe(i))
350 }
351 1 => {
352 let n = read_uint_trusted(self.data, &mut pos, ai, off)?;
353 let n_i = i64::try_from(n).map_err(|_| malformed(off))?;
354 Ok(CborIntegerRef::Safe(-1 - n_i))
355 }
356 6 => {
357 let tag = read_uint_trusted(self.data, &mut pos, ai, off)?;
358 let negative = match tag {
359 2 => false,
360 3 => true,
361 _ => return Err(expected_integer(off)),
362 };
363
364 let m_off = pos;
365 let first = read_u8_trusted(self.data, &mut pos)?;
366 let m_major = first >> 5;
367 let m_ai = first & 0x1f;
368 if m_major != 2 {
369 return Err(malformed(m_off));
370 }
371
372 let m_len = read_len_trusted(self.data, &mut pos, m_ai, m_off)?;
373 let mag = read_exact_trusted(self.data, &mut pos, m_len)?;
374
375 Ok(CborIntegerRef::Big(BigIntRef {
376 negative,
377 magnitude: mag,
378 }))
379 }
380 _ => Err(expected_integer(off)),
381 }
382 }
383
384 pub fn text(self) -> Result<&'a str, CborError> {
390 let mut pos = self.start;
391 let off = self.start;
392 let ib = read_u8_trusted(self.data, &mut pos)?;
393 let major = ib >> 5;
394 let ai = ib & 0x1f;
395
396 if major != 3 {
397 return Err(expected_text(off));
398 }
399
400 let len = read_len_trusted(self.data, &mut pos, ai, off)?;
401 let bytes = read_exact_trusted(self.data, &mut pos, len)?;
402 let s = utf8::trusted(bytes).map_err(|()| malformed(off))?;
403 Ok(s)
404 }
405
406 pub fn bytes(self) -> Result<&'a [u8], CborError> {
412 let mut pos = self.start;
413 let off = self.start;
414 let ib = read_u8_trusted(self.data, &mut pos)?;
415 let major = ib >> 5;
416 let ai = ib & 0x1f;
417
418 if major != 2 {
419 return Err(expected_bytes(off));
420 }
421
422 let len = read_len_trusted(self.data, &mut pos, ai, off)?;
423 let bytes = read_exact_trusted(self.data, &mut pos, len)?;
424 Ok(bytes)
425 }
426
427 pub fn bool(self) -> Result<bool, CborError> {
433 let off = self.start;
434 let b = *self.data.get(off).ok_or_else(|| malformed(off))?;
435
436 match b {
437 0xf4 => Ok(false),
438 0xf5 => Ok(true),
439 _ => Err(expected_bool(off)),
440 }
441 }
442
443 pub fn float64(self) -> Result<f64, CborError> {
449 let mut pos = self.start;
450 let off = self.start;
451 let ib = read_u8_trusted(self.data, &mut pos)?;
452 let major = ib >> 5;
453 let ai = ib & 0x1f;
454
455 if major != 7 || ai != 27 {
456 return Err(expected_float(off));
457 }
458
459 let b = read_exact_trusted(self.data, &mut pos, 8)?;
460 let bits = u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]);
461 Ok(f64::from_bits(bits))
462 }
463}
464
465impl PartialEq for CborValueRef<'_> {
466 fn eq(&self, other: &Self) -> bool {
467 self.as_bytes() == other.as_bytes()
468 }
469}
470
471impl Eq for CborValueRef<'_> {}
472
473#[derive(Debug, Clone, Copy)]
478pub struct MapRef<'a> {
479 data: &'a [u8],
480 map_off: usize,
481 entries_start: usize,
482 len: usize,
483}
484
485impl<'a> MapRef<'a> {
486 #[must_use]
488 pub const fn len(self) -> usize {
489 self.len
490 }
491
492 #[must_use]
494 pub const fn is_empty(self) -> bool {
495 self.len == 0
496 }
497
498 pub fn get(self, key: &str) -> Result<Option<CborValueRef<'a>>, CborError> {
506 checked_text_len(key.len()).map_err(|code| CborError::new(code, self.map_off))?;
507 let mut pos = self.entries_start;
508 let mut scratch = wire::SkipScratch::new();
509
510 for _ in 0..self.len {
511 let key_off = pos;
512 let mut key_pos = pos;
513 let key_bytes = read_text_bytes(self.data, &mut key_pos)?;
514 let value_start = key_pos;
515
516 let cmp = cmp_text_key_bytes_to_query(key_bytes, key);
517 match cmp {
518 Ordering::Less => {
519 pos = value_end_with_scratch(self.data, value_start, &mut scratch)?;
520 }
521 Ordering::Equal => {
522 let end = value_end_with_scratch(self.data, value_start, &mut scratch)?;
523 return Ok(Some(CborValueRef::new(self.data, value_start, end)));
524 }
525 Ordering::Greater => return Ok(None),
526 }
527
528 if pos <= key_off {
530 return Err(malformed(key_off));
531 }
532 }
533
534 Ok(None)
535 }
536
537 pub fn require(self, key: &str) -> Result<CborValueRef<'a>, CborError> {
543 self.get(key)?.ok_or_else(|| missing_key(self.map_off))
544 }
545
546 pub fn require_many_sorted<const N: usize>(
552 self,
553 keys: [&str; N],
554 ) -> Result<[CborValueRef<'a>; N], CborError> {
555 let got = self.get_many_sorted(keys)?;
556 for v in &got {
557 if v.is_none() {
558 return Err(missing_key(self.map_off));
559 }
560 }
561
562 let mut err: Option<CborError> = None;
563 let data = self.data;
564 let off = self.map_off;
565 let out = core::array::from_fn(|i| {
566 got[i].unwrap_or_else(|| {
567 err = Some(missing_key(off));
568 CborValueRef::new(data, off, off)
569 })
570 });
571
572 if let Some(e) = err {
573 return Err(e);
574 }
575
576 Ok(out)
577 }
578
579 pub fn get_many_sorted<const N: usize>(
587 self,
588 keys: [&str; N],
589 ) -> Result<[Option<CborValueRef<'a>>; N], CborError> {
590 let mut out: [Option<CborValueRef<'a>>; N] = [None; N];
591
592 validate_query_keys(&keys, self.map_off)?;
593
594 if keys.is_empty() || self.len == 0 {
595 return Ok(out);
596 }
597
598 let mut idxs: [usize; N] = core::array::from_fn(|i| i);
599 idxs[..].sort_unstable_by(|&i, &j| cmp_text_keys_canonical(keys[i], keys[j]));
600
601 for w in idxs.windows(2) {
602 if keys[w[0]] == keys[w[1]] {
603 return Err(CborError::new(ErrorCode::InvalidQuery, self.map_off));
604 }
605 }
606
607 let mut state = MapScanState::new(self.data, self.entries_start, self.len);
608 state.scan_sorted(&keys, &idxs, |out_idx, value_start, end| {
609 out[out_idx] = Some(CborValueRef::new(self.data, value_start, end));
610 })?;
611
612 Ok(out)
613 }
614
615 #[cfg(feature = "alloc")]
623 pub fn get_many_sorted_into(
624 self,
625 keys: &[&str],
626 out: &mut [Option<CborValueRef<'a>>],
627 ) -> Result<(), CborError> {
628 self.get_many_into(keys, out)
629 }
630
631 pub fn iter(self) -> impl Iterator<Item = Result<(&'a str, CborValueRef<'a>), CborError>> + 'a {
635 MapIter {
636 data: self.data,
637 pos: self.entries_start,
638 remaining: self.len,
639 scratch: wire::SkipScratch::new(),
640 }
641 }
642
643 #[cfg(feature = "alloc")]
647 pub(crate) fn iter_encoded(
648 self,
649 ) -> impl Iterator<Item = Result<EncodedMapEntry<'a>, CborError>> + 'a {
650 MapIterEncoded {
651 data: self.data,
652 pos: self.entries_start,
653 remaining: self.len,
654 scratch: wire::SkipScratch::new(),
655 }
656 }
657
658 pub fn extras_sorted<'k>(
664 self,
665 used_keys: &'k [&'k str],
666 ) -> Result<impl Iterator<Item = Result<(&'a str, CborValueRef<'a>), CborError>> + 'k, CborError>
667 where
668 'a: 'k,
669 {
670 validate_query_keys(used_keys, self.map_off)?;
671 ensure_strictly_increasing_keys(used_keys, self.map_off)?;
672
673 let it = MapIter {
674 data: self.data,
675 pos: self.entries_start,
676 remaining: self.len,
677 scratch: wire::SkipScratch::new(),
678 };
679
680 Ok(ExtrasIter {
681 iter: it,
682 used: used_keys,
683 idx: 0,
684 })
685 }
686
687 #[cfg(feature = "alloc")]
693 pub fn extras_sorted_vec<'k>(
694 self,
695 used_keys: &'k [&'k str],
696 ) -> Result<Vec<(&'a str, CborValueRef<'a>)>, CborError>
697 where
698 'a: 'k,
699 {
700 use crate::alloc_util::try_vec_with_capacity;
701
702 let mut out = try_vec_with_capacity(self.len(), self.map_off)?;
703 for entry in self.extras_sorted(used_keys)? {
704 out.push(entry?);
705 }
706 Ok(out)
707 }
708
709 #[cfg(feature = "alloc")]
715 pub fn extras_vec<'k>(
716 self,
717 used_keys: &'k [&'k str],
718 ) -> Result<Vec<(&'a str, CborValueRef<'a>)>, CborError>
719 where
720 'a: 'k,
721 {
722 use crate::alloc_util::try_vec_with_capacity;
723
724 validate_query_keys(used_keys, self.map_off)?;
725 if used_keys.is_empty() {
726 return self.extras_sorted_vec(&[]);
727 }
728
729 let mut idxs = try_vec_with_capacity(used_keys.len(), self.map_off)?;
730 for idx in 0..used_keys.len() {
731 idxs.push(idx);
732 }
733 idxs.sort_by(|&i, &j| cmp_text_keys_canonical(used_keys[i], used_keys[j]));
734 for w in idxs.windows(2) {
735 if used_keys[w[0]] == used_keys[w[1]] {
736 return Err(CborError::new(ErrorCode::InvalidQuery, self.map_off));
737 }
738 }
739
740 let mut sorted = try_vec_with_capacity(used_keys.len(), self.map_off)?;
741 for idx in idxs {
742 sorted.push(used_keys[idx]);
743 }
744 self.extras_sorted_vec(&sorted)
745 }
746
747 #[cfg(feature = "alloc")]
755 pub fn get_many(self, keys: &[&str]) -> Result<Vec<Option<CborValueRef<'a>>>, CborError> {
756 let mut out = crate::alloc_util::try_vec_repeat_copy(keys.len(), None, self.map_off)?;
757 self.get_many_into(keys, &mut out)?;
758 Ok(out)
759 }
760
761 #[cfg(feature = "alloc")]
769 pub fn require_many(self, keys: &[&str]) -> Result<Vec<CborValueRef<'a>>, CborError> {
770 let mut out = crate::alloc_util::try_vec_repeat_copy(keys.len(), None, self.map_off)?;
771 self.get_many_into(keys, &mut out)?;
772
773 let mut req = crate::alloc_util::try_vec_with_capacity(out.len(), self.map_off)?;
774 for slot in out {
775 match slot {
776 Some(v) => req.push(v),
777 None => return Err(missing_key(self.map_off)),
778 }
779 }
780 Ok(req)
781 }
782
783 #[cfg(feature = "alloc")]
791 pub fn get_many_into(
792 self,
793 keys: &[&str],
794 out: &mut [Option<CborValueRef<'a>>],
795 ) -> Result<(), CborError> {
796 if keys.len() != out.len() {
797 return Err(CborError::new(ErrorCode::InvalidQuery, self.map_off));
798 }
799
800 validate_query_keys(keys, self.map_off)?;
801
802 for slot in out.iter_mut() {
803 *slot = None;
804 }
805
806 if keys.is_empty() || self.len == 0 {
807 return Ok(());
808 }
809
810 let mut idxs = crate::alloc_util::try_vec_with_capacity(keys.len(), self.map_off)?;
812 for i in 0..keys.len() {
813 idxs.push(i);
814 }
815 idxs.sort_by(|&i, &j| cmp_text_keys_canonical(keys[i], keys[j]));
816
817 for w in idxs.windows(2) {
819 if keys[w[0]] == keys[w[1]] {
820 return Err(CborError::new(ErrorCode::InvalidQuery, self.map_off));
821 }
822 }
823
824 let mut state = MapScanState::new(self.data, self.entries_start, self.len);
826 state.scan_sorted(keys, &idxs, |out_idx, value_start, end| {
827 out[out_idx] = Some(CborValueRef::new(self.data, value_start, end));
828 })?;
829
830 Ok(())
831 }
832}
833
834#[derive(Debug, Clone, Copy)]
836pub struct ArrayRef<'a> {
837 data: &'a [u8],
838 array_off: usize,
839 items_start: usize,
840 len: usize,
841}
842
843impl<'a> ArrayRef<'a> {
844 #[must_use]
846 pub const fn len(self) -> usize {
847 self.len
848 }
849
850 #[must_use]
852 pub const fn is_empty(self) -> bool {
853 self.len == 0
854 }
855
856 pub fn get(self, index: usize) -> Result<Option<CborValueRef<'a>>, CborError> {
862 if index >= self.len {
863 return Ok(None);
864 }
865
866 let mut pos = self.items_start;
867 let mut scratch = wire::SkipScratch::new();
868 for i in 0..self.len {
869 let start = pos;
870 let end = value_end_with_scratch(self.data, start, &mut scratch)?;
871 if i == index {
872 return Ok(Some(CborValueRef::new(self.data, start, end)));
873 }
874 pos = end;
875 }
876
877 Err(malformed(self.array_off))
878 }
879
880 pub fn iter(self) -> impl Iterator<Item = Result<CborValueRef<'a>, CborError>> + 'a {
884 ArrayIter {
885 data: self.data,
886 pos: self.items_start,
887 remaining: self.len,
888 scratch: wire::SkipScratch::new(),
889 }
890 }
891}
892
893impl<'a> CanonicalCborRef<'a> {
895 #[must_use]
900 pub const fn root(self) -> CborValueRef<'a> {
901 CborValueRef::new(self.as_bytes(), 0, self.len())
902 }
903
904 pub fn at(self, path: &[PathElem<'_>]) -> Result<Option<CborValueRef<'a>>, CborError> {
910 self.root().at(path)
911 }
912}
913
914#[cfg(feature = "alloc")]
915impl CanonicalCbor {
916 #[must_use]
918 pub fn root(&self) -> CborValueRef<'_> {
919 let b = self.as_bytes();
920 CborValueRef::new(b, 0, b.len())
921 }
922
923 pub fn at(&self, path: &[PathElem<'_>]) -> Result<Option<CborValueRef<'_>>, CborError> {
929 self.root().at(path)
930 }
931}
932
933#[inline]
938const fn map_trusted_err(cause: CborError) -> CborError {
939 err(ErrorCode::MalformedCanonical, cause.offset)
940}
941
942#[inline]
943fn read_u8_trusted(data: &[u8], pos: &mut usize) -> Result<u8, CborError> {
944 wire::read_u8(data, pos).map_err(map_trusted_err)
945}
946
947#[inline]
948fn read_exact_trusted<'a>(
949 data: &'a [u8],
950 pos: &mut usize,
951 n: usize,
952) -> Result<&'a [u8], CborError> {
953 wire::read_exact(data, pos, n).map_err(map_trusted_err)
954}
955
956#[inline]
957fn read_uint_trusted(data: &[u8], pos: &mut usize, ai: u8, off: usize) -> Result<u64, CborError> {
958 wire::read_uint_trusted(data, pos, ai, off).map_err(map_trusted_err)
959}
960
961#[inline]
962fn read_len_trusted(data: &[u8], pos: &mut usize, ai: u8, off: usize) -> Result<usize, CborError> {
963 wire::read_len_trusted(data, pos, ai, off).map_err(map_trusted_err)
964}
965
966#[derive(Clone, Copy)]
967struct CachedKey<'a> {
968 key_bytes: &'a [u8],
969 value_start: usize,
970}
971
972struct MapScanState<'a> {
973 data: &'a [u8],
974 pos: usize,
975 cached: Option<CachedKey<'a>>,
976 map_remaining: usize,
977 scratch: wire::SkipScratch,
978}
979
980impl<'a> MapScanState<'a> {
981 const fn new(data: &'a [u8], pos: usize, map_remaining: usize) -> Self {
982 Self {
983 data,
984 pos,
985 cached: None,
986 map_remaining,
987 scratch: wire::SkipScratch::new(),
988 }
989 }
990
991 fn fill_cache(&mut self) -> Result<(), CborError> {
992 if self.cached.is_none() {
993 let mut key_pos = self.pos;
994 let key_bytes = read_text_bytes(self.data, &mut key_pos)?;
995 let value_start = key_pos;
996 self.pos = value_start;
997 self.cached = Some(CachedKey {
998 key_bytes,
999 value_start,
1000 });
1001 }
1002 Ok(())
1003 }
1004
1005 fn consume_cached_entry(&mut self, ck: CachedKey<'a>) -> Result<usize, CborError> {
1006 let end = value_end_with_scratch(self.data, ck.value_start, &mut self.scratch)?;
1007 self.pos = end;
1008 self.cached = None;
1009 self.map_remaining -= 1;
1010 Ok(end)
1011 }
1012
1013 fn handle_query_match<F>(
1014 &mut self,
1015 query: &str,
1016 q_idx: usize,
1017 on_match: F,
1018 ) -> Result<usize, CborError>
1019 where
1020 F: FnOnce(usize),
1021 {
1022 let Some(ck) = self.cached else {
1023 return Ok(q_idx);
1024 };
1025
1026 match cmp_text_key_bytes_to_query(ck.key_bytes, query) {
1027 Ordering::Less => {
1028 let _ = self.consume_cached_entry(ck)?;
1029 Ok(q_idx)
1030 }
1031 Ordering::Equal => {
1032 let end = self.consume_cached_entry(ck)?;
1033 on_match(end);
1034 Ok(q_idx + 1)
1035 }
1036 Ordering::Greater => Ok(q_idx + 1),
1037 }
1038 }
1039
1040 fn scan_sorted<F>(
1041 &mut self,
1042 keys: &[&str],
1043 idxs: &[usize],
1044 mut on_match: F,
1045 ) -> Result<(), CborError>
1046 where
1047 F: FnMut(usize, usize, usize),
1048 {
1049 let mut q_pos = 0usize;
1050
1051 while q_pos < idxs.len() {
1052 if self.map_remaining == 0 {
1053 break;
1054 }
1055
1056 self.fill_cache()?;
1057
1058 let Some(ck) = self.cached else {
1059 continue;
1060 };
1061
1062 let out_idx = idxs[q_pos];
1063 let value_start = ck.value_start;
1064 q_pos = self.handle_query_match(keys[out_idx], q_pos, |end| {
1065 on_match(out_idx, value_start, end);
1066 })?;
1067 }
1068
1069 Ok(())
1070 }
1071}
1072
1073fn read_text<'a>(data: &'a [u8], pos: &mut usize) -> Result<&'a str, CborError> {
1074 let off = *pos;
1075 let ib = read_u8_trusted(data, pos)?;
1076 let major = ib >> 5;
1077 let ai = ib & 0x1f;
1078
1079 if major != 3 {
1080 return Err(malformed(off));
1081 }
1082
1083 let len = read_len_trusted(data, pos, ai, off)?;
1084 let bytes = read_exact_trusted(data, pos, len)?;
1085 let text = utf8::trusted(bytes).map_err(|()| malformed(off))?;
1086 Ok(text)
1087}
1088
1089fn read_text_bytes<'a>(data: &'a [u8], pos: &mut usize) -> Result<&'a [u8], CborError> {
1090 let off = *pos;
1091 let ib = read_u8_trusted(data, pos)?;
1092 let major = ib >> 5;
1093 let ai = ib & 0x1f;
1094
1095 if major != 3 {
1096 return Err(malformed(off));
1097 }
1098
1099 let len = read_len_trusted(data, pos, ai, off)?;
1100 read_exact_trusted(data, pos, len)
1101}
1102
1103fn value_end_with_scratch(
1104 data: &[u8],
1105 start: usize,
1106 scratch: &mut wire::SkipScratch,
1107) -> Result<usize, CborError> {
1108 let mut cursor = wire::Cursor::<CborError>::with_pos(data, start);
1109 let mut items_seen = 0;
1110 wire::skip_one_value_with_scratch::<false, CborError>(
1111 &mut cursor,
1112 None,
1113 &mut items_seen,
1114 0,
1115 scratch,
1116 )?;
1117 Ok(cursor.position())
1118}
1119
1120fn parse_map_header(data: &[u8], start: usize) -> Result<(usize, usize), CborError> {
1121 let mut pos = start;
1122 let off = start;
1123 let ib = read_u8_trusted(data, &mut pos)?;
1124 let major = ib >> 5;
1125 let ai = ib & 0x1f;
1126
1127 if major != 5 {
1128 return Err(expected_map(off));
1129 }
1130
1131 let len = read_len_trusted(data, &mut pos, ai, off)?;
1132 Ok((len, pos))
1133}
1134
1135fn parse_array_header(data: &[u8], start: usize) -> Result<(usize, usize), CborError> {
1136 let mut pos = start;
1137 let off = start;
1138 let ib = read_u8_trusted(data, &mut pos)?;
1139 let major = ib >> 5;
1140 let ai = ib & 0x1f;
1141
1142 if major != 4 {
1143 return Err(expected_array(off));
1144 }
1145
1146 let len = read_len_trusted(data, &mut pos, ai, off)?;
1147 Ok((len, pos))
1148}
1149
1150fn cmp_text_key_bytes_to_query(key_payload: &[u8], query: &str) -> Ordering {
1151 let q_bytes = query.as_bytes();
1152 match key_payload.len().cmp(&q_bytes.len()) {
1153 Ordering::Equal => key_payload.cmp(q_bytes),
1154 other => other,
1155 }
1156}
1157
1158fn validate_query_keys(keys: &[&str], err_off: usize) -> Result<(), CborError> {
1159 for &k in keys {
1160 checked_text_len(k.len()).map_err(|code| CborError::new(code, err_off))?;
1161 }
1162 Ok(())
1163}
1164
1165fn ensure_strictly_increasing_keys(keys: &[&str], err_off: usize) -> Result<(), CborError> {
1166 let mut prev: Option<&str> = None;
1167
1168 for &k in keys {
1169 if let Some(p) = prev {
1170 match cmp_text_keys_canonical(p, k) {
1171 Ordering::Less => {}
1172 Ordering::Equal | Ordering::Greater => {
1173 return Err(CborError::new(ErrorCode::InvalidQuery, err_off));
1174 }
1175 }
1176 }
1177 prev = Some(k);
1178 }
1179
1180 Ok(())
1181}
1182
1183struct ExtrasIter<'a, 'k> {
1184 iter: MapIter<'a>,
1185 used: &'k [&'k str],
1186 idx: usize,
1187}
1188
1189impl<'a> Iterator for ExtrasIter<'a, '_> {
1190 type Item = Result<(&'a str, CborValueRef<'a>), CborError>;
1191
1192 fn next(&mut self) -> Option<Self::Item> {
1193 loop {
1194 let next = self.iter.next()?;
1195 return match next {
1196 Err(e) => Some(Err(e)),
1197 Ok((k, v)) => {
1198 while self.idx < self.used.len()
1199 && cmp_text_keys_canonical(self.used[self.idx], k) == Ordering::Less
1200 {
1201 self.idx += 1;
1202 }
1203 if self.idx < self.used.len()
1204 && cmp_text_keys_canonical(self.used[self.idx], k) == Ordering::Equal
1205 {
1206 self.idx += 1;
1207 continue;
1208 }
1209 Some(Ok((k, v)))
1210 }
1211 };
1212 }
1213 }
1214}
1215
1216struct MapIter<'a> {
1217 data: &'a [u8],
1218 pos: usize,
1219 remaining: usize,
1220 scratch: wire::SkipScratch,
1221}
1222
1223impl<'a> Iterator for MapIter<'a> {
1224 type Item = Result<(&'a str, CborValueRef<'a>), CborError>;
1225
1226 fn next(&mut self) -> Option<Self::Item> {
1227 if self.remaining == 0 {
1228 return None;
1229 }
1230
1231 let mut key_pos = self.pos;
1232 let parsed = match read_text(self.data, &mut key_pos) {
1233 Ok(v) => v,
1234 Err(e) => {
1235 self.remaining = 0;
1236 return Some(Err(e));
1237 }
1238 };
1239
1240 let value_start = key_pos;
1241 let end = match value_end_with_scratch(self.data, value_start, &mut self.scratch) {
1242 Ok(e) => e,
1243 Err(e) => {
1244 self.remaining = 0;
1245 return Some(Err(e));
1246 }
1247 };
1248
1249 self.pos = end;
1250 self.remaining -= 1;
1251
1252 Some(Ok((parsed, CborValueRef::new(self.data, value_start, end))))
1253 }
1254}
1255
1256#[cfg(feature = "alloc")]
1257type EncodedMapEntry<'a> = (&'a str, EncodedTextKey<'a>, CborValueRef<'a>);
1258
1259#[cfg(feature = "alloc")]
1260struct MapIterEncoded<'a> {
1261 data: &'a [u8],
1262 pos: usize,
1263 remaining: usize,
1264 scratch: wire::SkipScratch,
1265}
1266
1267#[cfg(feature = "alloc")]
1268impl<'a> Iterator for MapIterEncoded<'a> {
1269 type Item = Result<EncodedMapEntry<'a>, CborError>;
1270
1271 fn next(&mut self) -> Option<Self::Item> {
1272 if self.remaining == 0 {
1273 return None;
1274 }
1275
1276 let key_start = self.pos;
1277 let mut key_pos = self.pos;
1278 let parsed = match read_text(self.data, &mut key_pos) {
1279 Ok(v) => v,
1280 Err(e) => {
1281 self.remaining = 0;
1282 return Some(Err(e));
1283 }
1284 };
1285 let key_end = key_pos;
1286
1287 let value_start = key_end;
1288 let end = match value_end_with_scratch(self.data, value_start, &mut self.scratch) {
1289 Ok(e) => e,
1290 Err(e) => {
1291 self.remaining = 0;
1292 return Some(Err(e));
1293 }
1294 };
1295
1296 self.pos = end;
1297 self.remaining -= 1;
1298
1299 Some(Ok((
1300 parsed,
1301 EncodedTextKey::new_unchecked(&self.data[key_start..key_end]),
1302 CborValueRef::new(self.data, value_start, end),
1303 )))
1304 }
1305}
1306
1307struct ArrayIter<'a> {
1308 data: &'a [u8],
1309 pos: usize,
1310 remaining: usize,
1311 scratch: wire::SkipScratch,
1312}
1313
1314impl<'a> Iterator for ArrayIter<'a> {
1315 type Item = Result<CborValueRef<'a>, CborError>;
1316
1317 fn next(&mut self) -> Option<Self::Item> {
1318 if self.remaining == 0 {
1319 return None;
1320 }
1321
1322 let start = self.pos;
1323 let end = match value_end_with_scratch(self.data, start, &mut self.scratch) {
1324 Ok(e) => e,
1325 Err(e) => {
1326 self.remaining = 0;
1327 return Some(Err(e));
1328 }
1329 };
1330
1331 self.pos = end;
1332 self.remaining -= 1;
1333
1334 Some(Ok(CborValueRef::new(self.data, start, end)))
1335 }
1336}