1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::cmp::Ordering;
5
6use crate::alloc_util::try_reserve;
7use crate::canonical::{CanonicalCbor, CanonicalCborRef, EncodedTextKey};
8use crate::encode::{ArrayEncoder, MapEncoder};
9use crate::profile::{checked_text_len, cmp_text_keys_canonical};
10use crate::query::{CborValueRef, PathElem};
11use crate::scalar::F64Bits;
12use crate::{CborError, Encoder, ErrorCode};
13
14const fn err(code: ErrorCode, offset: usize) -> CborError {
15 CborError::new(code, offset)
16}
17
18#[cold]
19#[inline(never)]
20const fn invalid_query() -> CborError {
21 err(ErrorCode::InvalidQuery, 0)
22}
23
24#[cold]
25#[inline(never)]
26const fn patch_conflict() -> CborError {
27 err(ErrorCode::PatchConflict, 0)
28}
29
30#[cold]
31#[inline(never)]
32const fn missing_key(offset: usize) -> CborError {
33 err(ErrorCode::MissingKey, offset)
34}
35
36#[cold]
37#[inline(never)]
38const fn index_out_of_bounds(offset: usize) -> CborError {
39 err(ErrorCode::IndexOutOfBounds, offset)
40}
41
42#[cold]
43#[inline(never)]
44const fn length_overflow(offset: usize) -> CborError {
45 err(ErrorCode::LengthOverflow, offset)
46}
47
48#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum SetMode {
52 Upsert,
54 InsertOnly,
56 ReplaceOnly,
58}
59
60#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum DeleteMode {
64 Require,
66 IfPresent,
68}
69
70#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum ArrayPos {
74 At(usize),
76 End,
78}
79
80#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
83pub struct EditOptions {
84 pub create_missing_maps: bool,
86}
87
88#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
90#[derive(Debug)]
91pub struct Editor<'a> {
92 root: CborValueRef<'a>,
93 options: EditOptions,
94 ops: Node<'a>,
95}
96
97impl<'a> Editor<'a> {
98 pub(crate) const fn new(root: CborValueRef<'a>) -> Self {
99 Self {
100 root,
101 options: EditOptions {
102 create_missing_maps: false,
103 },
104 ops: Node::new(),
105 }
106 }
107
108 pub fn options_mut(&mut self) -> &mut EditOptions {
110 &mut self.options
111 }
112
113 pub fn splice<'p>(
122 &'p mut self,
123 array_path: &'p [PathElem<'p>],
124 pos: ArrayPos,
125 delete: usize,
126 ) -> Result<ArraySpliceBuilder<'p, 'a, 'p>, CborError> {
127 if matches!(pos, ArrayPos::End) && delete != 0 {
128 return Err(invalid_query());
129 }
130 Ok(ArraySpliceBuilder {
131 editor: self,
132 path: array_path,
133 pos,
134 delete,
135 inserts: Vec::new(),
136 bounds: BoundsMode::Require,
137 })
138 }
139
140 pub fn push<T: EditEncode<'a>>(
146 &mut self,
147 array_path: &[PathElem<'_>],
148 value: T,
149 ) -> Result<(), CborError> {
150 self.splice(array_path, ArrayPos::End, 0)?
151 .insert(value)?
152 .finish()
153 }
154
155 pub fn push_encoded<F>(&mut self, array_path: &[PathElem<'_>], f: F) -> Result<(), CborError>
161 where
162 F: FnOnce(&mut Encoder) -> Result<(), CborError>,
163 {
164 self.splice(array_path, ArrayPos::End, 0)?
165 .insert_encoded(f)?
166 .finish()
167 }
168
169 pub fn set<T: EditEncode<'a>>(
177 &mut self,
178 path: &[PathElem<'_>],
179 value: T,
180 ) -> Result<(), CborError> {
181 self.set_with_mode(path, SetMode::Upsert, value)
182 }
183
184 pub fn insert<T: EditEncode<'a>>(
192 &mut self,
193 path: &[PathElem<'_>],
194 value: T,
195 ) -> Result<(), CborError> {
196 self.set_with_mode(path, SetMode::InsertOnly, value)
197 }
198
199 pub fn replace<T: EditEncode<'a>>(
207 &mut self,
208 path: &[PathElem<'_>],
209 value: T,
210 ) -> Result<(), CborError> {
211 self.set_with_mode(path, SetMode::ReplaceOnly, value)
212 }
213
214 pub fn set_raw(
220 &mut self,
221 path: &[PathElem<'_>],
222 value: CborValueRef<'a>,
223 ) -> Result<(), CborError> {
224 self.insert_terminal(
225 path,
226 Terminal::Set {
227 mode: SetMode::Upsert,
228 value: EditValue::raw(value),
229 },
230 )
231 }
232
233 pub fn set_encoded<F>(&mut self, path: &[PathElem<'_>], f: F) -> Result<(), CborError>
239 where
240 F: FnOnce(&mut Encoder) -> Result<(), CborError>,
241 {
242 let bytes = encode_with(f)?;
243 self.insert_terminal(
244 path,
245 Terminal::Set {
246 mode: SetMode::Upsert,
247 value: EditValue::bytes_owned(bytes),
248 },
249 )
250 }
251
252 pub fn delete(&mut self, path: &[PathElem<'_>]) -> Result<(), CborError> {
260 self.insert_terminal(
261 path,
262 Terminal::Delete {
263 mode: DeleteMode::Require,
264 },
265 )
266 }
267
268 pub fn delete_if_present(&mut self, path: &[PathElem<'_>]) -> Result<(), CborError> {
276 self.insert_terminal(
277 path,
278 Terminal::Delete {
279 mode: DeleteMode::IfPresent,
280 },
281 )
282 }
283
284 pub fn apply(self) -> Result<CanonicalCbor, CborError> {
290 let mut enc = Encoder::with_capacity(self.root.len());
291 emit_value(&mut enc, self.root, &self.ops, self.options)?;
292 enc.into_canonical()
293 }
294
295 fn set_with_mode<T: EditEncode<'a>>(
296 &mut self,
297 path: &[PathElem<'_>],
298 mode: SetMode,
299 value: T,
300 ) -> Result<(), CborError> {
301 let new_value = value.into_value()?;
302 self.insert_terminal(
303 path,
304 Terminal::Set {
305 mode,
306 value: new_value,
307 },
308 )
309 }
310
311 fn insert_terminal(
312 &mut self,
313 path: &[PathElem<'_>],
314 terminal: Terminal<'a>,
315 ) -> Result<(), CborError> {
316 if path.is_empty() {
317 return Err(invalid_query());
318 }
319 if let Some(PathElem::Index(index)) = path.last() {
320 let parent = &path[..path.len() - 1];
321 let splice = match terminal {
322 Terminal::Delete { mode } => ArraySplice {
323 pos: ArrayPos::At(*index),
324 delete: 1,
325 inserts: Vec::new(),
326 bounds: match mode {
327 DeleteMode::Require => BoundsMode::Require,
328 DeleteMode::IfPresent => BoundsMode::IfPresent,
329 },
330 },
331 Terminal::Set { mode, value } => {
332 let (delete, bounds) = match mode {
333 SetMode::InsertOnly => (0, BoundsMode::Require),
334 SetMode::Upsert | SetMode::ReplaceOnly => (1, BoundsMode::Require),
335 };
336 let mut inserts = crate::alloc_util::try_vec_with_capacity(1, 0)?;
337 inserts.push(value);
338 ArraySplice {
339 pos: ArrayPos::At(*index),
340 delete,
341 inserts,
342 bounds,
343 }
344 }
345 };
346 return self.ops.insert_splice(parent, splice);
347 }
348 self.ops.insert(path, terminal)
349 }
350}
351
352mod sealed {
353 pub trait Sealed {}
354}
355
356#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
358pub trait EditEncode<'a>: sealed::Sealed {
359 fn into_value(self) -> Result<EditValue<'a>, CborError>;
365}
366
367impl sealed::Sealed for bool {}
368impl sealed::Sealed for () {}
369impl sealed::Sealed for &str {}
370impl sealed::Sealed for String {}
371impl sealed::Sealed for &[u8] {}
372impl sealed::Sealed for Vec<u8> {}
373impl sealed::Sealed for F64Bits {}
374impl sealed::Sealed for f64 {}
375impl sealed::Sealed for f32 {}
376impl sealed::Sealed for i64 {}
377impl sealed::Sealed for u64 {}
378impl sealed::Sealed for i128 {}
379impl sealed::Sealed for u128 {}
380impl sealed::Sealed for CanonicalCborRef<'_> {}
381impl sealed::Sealed for CanonicalCbor {}
382impl sealed::Sealed for &CanonicalCbor {}
383
384impl<'a> EditEncode<'a> for bool {
385 fn into_value(self) -> Result<EditValue<'a>, CborError> {
386 encode_to_vec(|enc| enc.bool(self))
387 }
388}
389
390impl<'a> EditEncode<'a> for () {
391 fn into_value(self) -> Result<EditValue<'a>, CborError> {
392 encode_to_vec(Encoder::null)
393 }
394}
395
396impl<'a> EditEncode<'a> for &str {
397 fn into_value(self) -> Result<EditValue<'a>, CborError> {
398 encode_to_vec(|enc| enc.text(self))
399 }
400}
401
402impl<'a> EditEncode<'a> for String {
403 fn into_value(self) -> Result<EditValue<'a>, CborError> {
404 encode_to_vec(|enc| enc.text(self.as_str()))
405 }
406}
407
408impl<'a> EditEncode<'a> for &[u8] {
409 fn into_value(self) -> Result<EditValue<'a>, CborError> {
410 encode_to_vec(|enc| enc.bytes(self))
411 }
412}
413
414impl<'a> EditEncode<'a> for Vec<u8> {
415 fn into_value(self) -> Result<EditValue<'a>, CborError> {
416 encode_to_vec(|enc| enc.bytes(self.as_slice()))
417 }
418}
419
420impl<'a> EditEncode<'a> for F64Bits {
421 fn into_value(self) -> Result<EditValue<'a>, CborError> {
422 encode_to_vec(|enc| enc.float(self))
423 }
424}
425
426impl<'a> EditEncode<'a> for f64 {
427 fn into_value(self) -> Result<EditValue<'a>, CborError> {
428 encode_to_vec(|enc| enc.float(F64Bits::try_from_f64(self)?))
429 }
430}
431
432impl<'a> EditEncode<'a> for f32 {
433 fn into_value(self) -> Result<EditValue<'a>, CborError> {
434 encode_to_vec(|enc| enc.float(F64Bits::try_from_f64(f64::from(self))?))
435 }
436}
437
438impl<'a> EditEncode<'a> for i64 {
439 fn into_value(self) -> Result<EditValue<'a>, CborError> {
440 encode_to_vec(|enc| enc.int(self))
441 }
442}
443
444impl<'a> EditEncode<'a> for u64 {
445 fn into_value(self) -> Result<EditValue<'a>, CborError> {
446 encode_to_vec(|enc| {
447 if self > crate::MAX_SAFE_INTEGER {
448 return Err(CborError::new(
449 ErrorCode::IntegerOutsideSafeRange,
450 enc.len(),
451 ));
452 }
453 let v = i64::try_from(self)
454 .map_err(|_| CborError::new(ErrorCode::LengthOverflow, enc.len()))?;
455 enc.int(v)
456 })
457 }
458}
459
460impl<'a> EditEncode<'a> for i128 {
461 fn into_value(self) -> Result<EditValue<'a>, CborError> {
462 encode_to_vec(|enc| enc.int_i128(self))
463 }
464}
465
466impl<'a> EditEncode<'a> for u128 {
467 fn into_value(self) -> Result<EditValue<'a>, CborError> {
468 encode_to_vec(|enc| enc.int_u128(self))
469 }
470}
471
472impl<'a> EditEncode<'a> for CanonicalCborRef<'a> {
473 fn into_value(self) -> Result<EditValue<'a>, CborError> {
474 Ok(EditValue::bytes_ref(self))
475 }
476}
477
478impl<'a> EditEncode<'a> for CanonicalCbor {
479 fn into_value(self) -> Result<EditValue<'a>, CborError> {
480 Ok(EditValue::bytes_owned(self.into_bytes()))
481 }
482}
483
484impl<'a> EditEncode<'a> for &'a CanonicalCbor {
485 fn into_value(self) -> Result<EditValue<'a>, CborError> {
486 Ok(EditValue::bytes_ref(CanonicalCborRef::new(self.as_bytes())))
487 }
488}
489
490#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
492pub struct ArraySpliceBuilder<'e, 'a, 'p> {
493 editor: &'e mut Editor<'a>,
494 path: &'p [PathElem<'p>],
495 pos: ArrayPos,
496 delete: usize,
497 inserts: Vec<EditValue<'a>>,
498 bounds: BoundsMode,
499}
500
501impl<'a> ArraySpliceBuilder<'_, 'a, '_> {
502 pub fn insert<T: EditEncode<'a>>(mut self, value: T) -> Result<Self, CborError> {
508 let value = value.into_value()?;
509 try_reserve(&mut self.inserts, 1, 0)?;
510 self.inserts.push(value);
511 Ok(self)
512 }
513
514 pub fn insert_raw(mut self, value: CborValueRef<'a>) -> Result<Self, CborError> {
520 try_reserve(&mut self.inserts, 1, 0)?;
521 self.inserts.push(EditValue::raw(value));
522 Ok(self)
523 }
524
525 pub fn insert_encoded<F>(mut self, f: F) -> Result<Self, CborError>
531 where
532 F: FnOnce(&mut Encoder) -> Result<(), CborError>,
533 {
534 let bytes = encode_with(f)?;
535 try_reserve(&mut self.inserts, 1, 0)?;
536 self.inserts.push(EditValue::bytes_owned(bytes));
537 Ok(self)
538 }
539
540 pub fn finish(self) -> Result<(), CborError> {
546 let splice = ArraySplice {
547 pos: self.pos,
548 delete: self.delete,
549 inserts: self.inserts,
550 bounds: self.bounds,
551 };
552 self.editor.ops.insert_splice(self.path, splice)
553 }
554}
555
556#[derive(Debug, Clone)]
557enum Children<'a> {
558 None,
559 Keys(Vec<(Box<str>, Node<'a>)>),
560 Indices(Vec<(usize, Node<'a>)>),
561}
562
563impl Children<'_> {
564 fn is_empty(&self) -> bool {
565 match self {
566 Self::None => true,
567 Self::Keys(v) => v.is_empty(),
568 Self::Indices(v) => v.is_empty(),
569 }
570 }
571}
572
573#[derive(Debug, Clone)]
574enum Terminal<'a> {
575 Delete { mode: DeleteMode },
576 Set { mode: SetMode, value: EditValue<'a> },
577}
578
579#[derive(Debug, Clone, Copy, PartialEq, Eq)]
580enum BoundsMode {
581 Require,
582 IfPresent,
583}
584
585#[derive(Debug, Clone)]
586struct ArraySplice<'a> {
587 pos: ArrayPos,
588 delete: usize,
589 inserts: Vec<EditValue<'a>>,
590 bounds: BoundsMode,
591}
592
593fn cmp_array_pos(a: ArrayPos, b: ArrayPos) -> Ordering {
594 match (a, b) {
595 (ArrayPos::At(x), ArrayPos::At(y)) => x.cmp(&y),
596 (ArrayPos::At(_), ArrayPos::End) => Ordering::Less,
597 (ArrayPos::End, ArrayPos::At(_)) => Ordering::Greater,
598 (ArrayPos::End, ArrayPos::End) => Ordering::Equal,
599 }
600}
601
602fn splice_end(start: usize, delete: usize, offset: usize) -> Result<usize, CborError> {
603 start
604 .checked_add(delete)
605 .ok_or_else(|| CborError::new(ErrorCode::LengthOverflow, offset))
606}
607
608#[derive(Debug, Clone)]
609pub struct EditValue<'a>(EditValueInner<'a>);
611
612#[derive(Debug, Clone)]
613enum EditValueInner<'a> {
614 Raw(CborValueRef<'a>),
616 BytesRef(CanonicalCborRef<'a>),
618 BytesOwned(Vec<u8>),
620}
621
622impl<'a> EditValue<'a> {
623 pub(crate) const fn raw(value: CborValueRef<'a>) -> Self {
624 Self(EditValueInner::Raw(value))
625 }
626
627 pub(crate) const fn bytes_ref(value: CanonicalCborRef<'a>) -> Self {
628 Self(EditValueInner::BytesRef(value))
629 }
630
631 pub(crate) const fn bytes_owned(value: Vec<u8>) -> Self {
632 Self(EditValueInner::BytesOwned(value))
633 }
634}
635
636#[derive(Debug, Clone)]
637struct Node<'a> {
638 terminal: Option<Terminal<'a>>,
639 children: Children<'a>,
640 splices: Vec<ArraySplice<'a>>,
641}
642
643impl<'a> Node<'a> {
644 const fn new() -> Self {
645 Self {
646 terminal: None,
647 children: Children::None,
648 splices: Vec::new(),
649 }
650 }
651
652 fn is_empty(&self) -> bool {
653 self.terminal.is_none() && self.children.is_empty() && self.splices.is_empty()
654 }
655
656 fn insert(&mut self, path: &[PathElem<'_>], terminal: Terminal<'a>) -> Result<(), CborError> {
657 let mut cur = self;
658
659 for (idx, pe) in path.iter().enumerate() {
660 if cur.terminal.is_some() {
661 return Err(patch_conflict());
662 }
663
664 let child = cur.child_mut(pe)?;
665
666 if idx + 1 == path.len() {
667 if child.terminal.is_some()
668 || !child.children.is_empty()
669 || !child.splices.is_empty()
670 {
671 return Err(patch_conflict());
672 }
673 child.terminal = Some(terminal);
674 return Ok(());
675 }
676
677 cur = child;
678 }
679
680 Err(invalid_query())
681 }
682
683 fn insert_splice(
684 &mut self,
685 path: &[PathElem<'_>],
686 splice: ArraySplice<'a>,
687 ) -> Result<(), CborError> {
688 let mut cur = self;
689
690 for pe in path {
691 if cur.terminal.is_some() {
692 return Err(patch_conflict());
693 }
694 cur = cur.child_mut(pe)?;
695 }
696
697 if cur.terminal.is_some() {
698 return Err(patch_conflict());
699 }
700 cur.ensure_index_context()?;
701
702 if matches!(splice.pos, ArrayPos::End) && splice.delete != 0 {
703 return Err(invalid_query());
704 }
705
706 let Err(insert_idx) = cur
707 .splices
708 .binary_search_by(|s| cmp_array_pos(s.pos, splice.pos))
709 else {
710 return Err(patch_conflict());
711 };
712
713 if let ArrayPos::At(new_pos) = splice.pos {
714 if let Some(prev) = insert_idx
715 .checked_sub(1)
716 .and_then(|idx| cur.splices.get(idx))
717 {
718 if let ArrayPos::At(prev_pos) = prev.pos {
719 let prev_end = splice_end(prev_pos, prev.delete, 0)?;
720 if new_pos < prev_end {
721 return Err(patch_conflict());
722 }
723 }
724 }
725 if let Some(next) = cur.splices.get(insert_idx) {
726 if let ArrayPos::At(next_pos) = next.pos {
727 let new_end = splice_end(new_pos, splice.delete, 0)?;
728 if next_pos < new_end {
729 return Err(patch_conflict());
730 }
731 }
732 }
733 }
734
735 try_reserve(&mut cur.splices, 1, 0)?;
736 cur.splices.insert(insert_idx, splice);
737 Ok(())
738 }
739
740 fn child_mut(&mut self, elem: &PathElem<'_>) -> Result<&mut Self, CborError> {
741 match elem {
742 PathElem::Key(k) => {
743 checked_text_len(k.len()).map_err(|code| CborError::new(code, 0))?;
744 if matches!(&self.children, Children::None) {
745 self.children = Children::Keys(Vec::new());
746 } else if matches!(&self.children, Children::Indices(_)) {
747 return Err(patch_conflict());
748 }
749
750 let Children::Keys(children) = &mut self.children else {
751 return Err(patch_conflict());
752 };
753
754 match children
755 .binary_search_by(|(owned, _)| cmp_text_keys_canonical(owned.as_ref(), k))
756 {
757 Ok(idx) => Ok(&mut children[idx].1),
758 Err(idx) => {
759 let owned = crate::alloc_util::try_box_str_from_str(k, 0)?;
760 try_reserve(children, 1, 0)?;
761 children.insert(idx, (owned, Node::new()));
762 Ok(&mut children[idx].1)
763 }
764 }
765 }
766 PathElem::Index(i) => {
767 if matches!(&self.children, Children::None) {
768 self.children = Children::Indices(Vec::new());
769 } else if matches!(&self.children, Children::Keys(_)) {
770 return Err(patch_conflict());
771 }
772
773 let Children::Indices(children) = &mut self.children else {
774 return Err(patch_conflict());
775 };
776
777 match children.binary_search_by(|(owned, _)| owned.cmp(i)) {
778 Ok(idx) => Ok(&mut children[idx].1),
779 Err(idx) => {
780 try_reserve(children, 1, 0)?;
781 children.insert(idx, (*i, Node::new()));
782 Ok(&mut children[idx].1)
783 }
784 }
785 }
786 }
787 }
788
789 fn ensure_index_context(&mut self) -> Result<(), CborError> {
790 if matches!(&self.children, Children::None) {
791 self.children = Children::Indices(Vec::new());
792 return Ok(());
793 }
794 if matches!(&self.children, Children::Keys(_)) {
795 return Err(patch_conflict());
796 }
797 Ok(())
798 }
799
800 fn key_children(&self, offset: usize) -> Result<&[(Box<str>, Self)], CborError> {
801 match &self.children {
802 Children::None => Ok(&[]),
803 Children::Keys(children) => Ok(children.as_slice()),
804 Children::Indices(_) => Err(err(ErrorCode::ExpectedMap, offset)),
805 }
806 }
807
808 fn index_children(&self, offset: usize) -> Result<&[(usize, Self)], CborError> {
809 match &self.children {
810 Children::None => Ok(&[]),
811 Children::Indices(children) => Ok(children.as_slice()),
812 Children::Keys(_) => Err(err(ErrorCode::ExpectedArray, offset)),
813 }
814 }
815}
816
817struct ResolvedSplice<'a> {
818 start: usize,
819 delete: usize,
820 inserts: &'a [EditValue<'a>],
821}
822
823fn encode_with<F>(f: F) -> Result<Vec<u8>, CborError>
824where
825 F: FnOnce(&mut Encoder) -> Result<(), CborError>,
826{
827 let mut enc = Encoder::new();
828 f(&mut enc)?;
829 Ok(enc.into_canonical()?.into_bytes())
830}
831
832fn encode_to_vec<'a, F>(f: F) -> Result<EditValue<'a>, CborError>
833where
834 F: FnOnce(&mut Encoder) -> Result<(), CborError>,
835{
836 let bytes = encode_with(f)?;
837 Ok(EditValue::bytes_owned(bytes))
838}
839
840trait ValueEncoder {
841 fn raw_value_ref(&mut self, v: CborValueRef<'_>) -> Result<(), CborError>;
842 fn raw_cbor(&mut self, v: CanonicalCborRef<'_>) -> Result<(), CborError>;
843 fn map<F>(&mut self, len: usize, f: F) -> Result<(), CborError>
844 where
845 F: FnOnce(&mut MapEncoder<'_>) -> Result<(), CborError>;
846 fn array<F>(&mut self, len: usize, f: F) -> Result<(), CborError>
847 where
848 F: FnOnce(&mut ArrayEncoder<'_>) -> Result<(), CborError>;
849}
850
851impl ValueEncoder for Encoder {
852 fn raw_value_ref(&mut self, v: CborValueRef<'_>) -> Result<(), CborError> {
853 Self::raw_value_ref(self, v)
854 }
855
856 fn raw_cbor(&mut self, v: CanonicalCborRef<'_>) -> Result<(), CborError> {
857 Self::raw_cbor(self, v)
858 }
859
860 fn map<F>(&mut self, len: usize, f: F) -> Result<(), CborError>
861 where
862 F: FnOnce(&mut MapEncoder<'_>) -> Result<(), CborError>,
863 {
864 Self::map(self, len, f)
865 }
866
867 fn array<F>(&mut self, len: usize, f: F) -> Result<(), CborError>
868 where
869 F: FnOnce(&mut ArrayEncoder<'_>) -> Result<(), CborError>,
870 {
871 Self::array(self, len, f)
872 }
873}
874
875impl ValueEncoder for ArrayEncoder<'_> {
876 fn raw_value_ref(&mut self, v: CborValueRef<'_>) -> Result<(), CborError> {
877 ArrayEncoder::raw_value_ref(self, v)
878 }
879
880 fn raw_cbor(&mut self, v: CanonicalCborRef<'_>) -> Result<(), CborError> {
881 ArrayEncoder::raw_cbor(self, v)
882 }
883
884 fn map<F>(&mut self, len: usize, f: F) -> Result<(), CborError>
885 where
886 F: FnOnce(&mut MapEncoder<'_>) -> Result<(), CborError>,
887 {
888 ArrayEncoder::map(self, len, f)
889 }
890
891 fn array<F>(&mut self, len: usize, f: F) -> Result<(), CborError>
892 where
893 F: FnOnce(&mut ArrayEncoder<'_>) -> Result<(), CborError>,
894 {
895 ArrayEncoder::array(self, len, f)
896 }
897}
898
899fn write_new_value<E: ValueEncoder>(enc: &mut E, value: &EditValue<'_>) -> Result<(), CborError> {
900 match &value.0 {
901 EditValueInner::Raw(v) => enc.raw_value_ref(*v),
902 EditValueInner::BytesRef(b) => enc.raw_cbor(*b),
903 EditValueInner::BytesOwned(b) => enc.raw_cbor(CanonicalCborRef::new(b.as_slice())),
904 }
905}
906
907fn emit_value<'a, E: ValueEncoder>(
908 enc: &mut E,
909 src: CborValueRef<'a>,
910 node: &Node<'a>,
911 options: EditOptions,
912) -> Result<(), CborError> {
913 if node.is_empty() {
914 return enc.raw_value_ref(src);
915 }
916
917 if let Some(term) = node.terminal.as_ref() {
918 return match term {
919 Terminal::Set { value, .. } => write_new_value(enc, value),
920 Terminal::Delete { .. } => Err(invalid_query()),
921 };
922 }
923
924 match node.children {
925 Children::None => enc.raw_value_ref(src),
926 Children::Keys(_) => emit_patched_map(enc, src, node, options),
927 Children::Indices(_) => emit_patched_array(enc, src, node, options),
928 }
929}
930
931fn emit_patched_map<'a, E: ValueEncoder>(
932 enc: &mut E,
933 src: CborValueRef<'a>,
934 node: &Node<'a>,
935 options: EditOptions,
936) -> Result<(), CborError> {
937 let map = src.map()?;
938 let map_off = src.offset();
939 let mods = node.key_children(map_off)?;
940
941 if mods.is_empty() {
942 return enc.raw_value_ref(src);
943 }
944
945 let out_len = compute_map_len_and_validate(map, mods, options, map_off)?;
946 enc.map(out_len, |menc| {
947 emit_map_entries(menc, map, mods, options, map_off)
948 })
949}
950
951fn emit_patched_array<'a, E: ValueEncoder>(
952 enc: &mut E,
953 src: CborValueRef<'a>,
954 node: &Node<'a>,
955 options: EditOptions,
956) -> Result<(), CborError> {
957 let array = src.array()?;
958 let len = array.len();
959 let array_off = src.offset();
960 let mods = node.index_children(array_off)?;
961 let splices = collect_splices(node, len, array_off)?;
962
963 if mods.is_empty() && splices.is_empty() {
964 return enc.raw_value_ref(src);
965 }
966
967 if let Some(max) = mods.last().map(|m| m.0) {
968 if max >= len {
969 return Err(index_out_of_bounds(array_off));
970 }
971 }
972
973 ensure_splice_mod_conflicts(mods, &splices, array_off)?;
974 let out_len = compute_array_out_len(len, &splices, array_off)?;
975
976 enc.array(out_len, |aenc| {
977 emit_array_items(aenc, array, mods, &splices, options, array_off, len)
978 })
979}
980
981fn ensure_splice_mod_conflicts<'a>(
982 mods: &[(usize, Node<'a>)],
983 splices: &[ResolvedSplice<'a>],
984 offset: usize,
985) -> Result<(), CborError> {
986 if mods.is_empty() || splices.is_empty() {
987 return Ok(());
988 }
989 let mut mod_idx = 0usize;
990 for splice in splices {
991 if splice.delete == 0 {
992 continue;
993 }
994 let end_idx = splice
995 .start
996 .checked_add(splice.delete)
997 .ok_or_else(|| length_overflow(offset))?;
998 while mod_idx < mods.len() && mods[mod_idx].0 < splice.start {
999 mod_idx += 1;
1000 }
1001 if mod_idx < mods.len() && mods[mod_idx].0 < end_idx {
1002 return Err(patch_conflict());
1003 }
1004 }
1005 Ok(())
1006}
1007
1008fn compute_array_out_len(
1009 len: usize,
1010 splices: &[ResolvedSplice<'_>],
1011 offset: usize,
1012) -> Result<usize, CborError> {
1013 let mut out_len = len;
1014 for splice in splices {
1015 out_len = out_len
1016 .checked_sub(splice.delete)
1017 .ok_or_else(|| length_overflow(offset))?;
1018 out_len = out_len
1019 .checked_add(splice.inserts.len())
1020 .ok_or_else(|| length_overflow(offset))?;
1021 }
1022 Ok(out_len)
1023}
1024
1025fn emit_array_items<'a, E: ValueEncoder>(
1026 aenc: &mut E,
1027 array: crate::query::ArrayRef<'a>,
1028 mods: &[(usize, Node<'a>)],
1029 splices: &[ResolvedSplice<'a>],
1030 options: EditOptions,
1031 array_off: usize,
1032 len: usize,
1033) -> Result<(), CborError> {
1034 let mut splice_iter = splices.iter().peekable();
1035 let mut mods_iter = mods.iter().peekable();
1036 let mut iter = array.iter();
1037 let mut idx = 0usize;
1038
1039 while idx < len {
1040 if let Some(splice) = splice_iter.peek() {
1041 if splice.start == idx {
1042 for value in splice.inserts {
1043 write_new_value(aenc, value)?;
1044 }
1045 let delete = splice.delete;
1046 splice_iter.next();
1047 if delete > 0 {
1048 for _ in 0..delete {
1049 let item = iter
1050 .next()
1051 .ok_or_else(|| err(ErrorCode::MalformedCanonical, array_off))??;
1052 let _ = item;
1053 }
1054 idx = idx
1055 .checked_add(delete)
1056 .ok_or_else(|| length_overflow(array_off))?;
1057 continue;
1058 }
1059 }
1060 }
1061
1062 let item = iter
1063 .next()
1064 .ok_or_else(|| err(ErrorCode::MalformedCanonical, array_off))??;
1065 match mods_iter.peek() {
1066 Some((m_idx, _)) if *m_idx == idx => {
1067 let m_entry = mods_iter.next().ok_or_else(invalid_query)?;
1068 let m_node = &m_entry.1;
1069 if let Some(term) = m_node.terminal.as_ref() {
1070 match term {
1071 Terminal::Delete { .. } => return Err(invalid_query()),
1072 Terminal::Set { mode, value } => {
1073 if *mode == SetMode::InsertOnly {
1074 return Err(invalid_query());
1075 }
1076 write_new_value(aenc, value)?;
1077 }
1078 }
1079 } else {
1080 emit_value(aenc, item, m_node, options)?;
1081 }
1082 }
1083 _ => aenc.raw_value_ref(item)?,
1084 }
1085 idx += 1;
1086 }
1087
1088 for splice in splice_iter {
1089 if splice.start != len {
1090 return Err(index_out_of_bounds(array_off));
1091 }
1092 for value in splice.inserts {
1093 write_new_value(aenc, value)?;
1094 }
1095 }
1096
1097 if mods_iter.peek().is_some() {
1098 return Err(index_out_of_bounds(array_off));
1099 }
1100
1101 Ok(())
1102}
1103
1104fn collect_splices<'a>(
1105 node: &'a Node<'a>,
1106 len: usize,
1107 offset: usize,
1108) -> Result<Vec<ResolvedSplice<'a>>, CborError> {
1109 let mut out = crate::alloc_util::try_vec_with_capacity(node.splices.len(), offset)?;
1110 let mut last_start: Option<usize> = None;
1111 for splice in &node.splices {
1112 if matches!(splice.pos, ArrayPos::End) && splice.delete != 0 {
1113 return Err(invalid_query());
1114 }
1115 let start = match splice.pos {
1116 ArrayPos::At(i) => i,
1117 ArrayPos::End => len,
1118 };
1119
1120 if start >= len {
1121 if splice.bounds == BoundsMode::IfPresent {
1122 continue;
1123 }
1124 if start > len || splice.delete != 0 {
1125 return Err(index_out_of_bounds(offset));
1126 }
1127 }
1128
1129 let remaining = len
1130 .checked_sub(start)
1131 .ok_or_else(|| index_out_of_bounds(offset))?;
1132 if splice.delete > remaining {
1133 return Err(index_out_of_bounds(offset));
1134 }
1135
1136 if let Some(prev) = last_start {
1137 if start <= prev {
1138 return Err(patch_conflict());
1139 }
1140 }
1141 last_start = Some(start);
1142
1143 out.push(ResolvedSplice {
1144 start,
1145 delete: splice.delete,
1146 inserts: splice.inserts.as_slice(),
1147 });
1148 }
1149
1150 Ok(out)
1151}
1152
1153fn compute_map_len_and_validate<'a>(
1154 map: crate::query::MapRef<'a>,
1155 mods: &[(Box<str>, Node<'a>)],
1156 options: EditOptions,
1157 map_off: usize,
1158) -> Result<usize, CborError> {
1159 let mut out_len = map.len();
1160 let mut mod_idx = 0usize;
1161 let mut iter = map.iter();
1162 let mut entry = next_map_entry(&mut iter)?;
1163
1164 while entry.is_some() || mod_idx < mods.len() {
1165 let cur_mod = mods.get(mod_idx);
1166 match (entry, cur_mod) {
1167 (Some((key, _value)), Some((mod_key, mod_node))) => {
1168 match cmp_text_keys_canonical(key, mod_key.as_ref()) {
1169 Ordering::Less => {
1170 entry = next_map_entry(&mut iter)?;
1171 }
1172 Ordering::Equal => {
1173 match mod_node.terminal.as_ref() {
1174 Some(Terminal::Delete { .. }) => {
1175 out_len = out_len
1176 .checked_sub(1)
1177 .ok_or_else(|| length_overflow(map_off))?;
1178 }
1179 Some(Terminal::Set {
1180 mode: SetMode::InsertOnly,
1181 ..
1182 }) => {
1183 return Err(err(ErrorCode::InvalidQuery, map_off));
1184 }
1185 _ => {}
1186 }
1187 mod_idx += 1;
1188 entry = next_map_entry(&mut iter)?;
1189 }
1190 Ordering::Greater => {
1191 out_len = handle_missing_map_mod(out_len, mod_node, options, map_off)?;
1192 mod_idx += 1;
1193 }
1194 }
1195 }
1196 (Some((_key, _value)), None) => {
1197 entry = next_map_entry(&mut iter)?;
1198 }
1199 (None, Some((_mod_key, mod_node))) => {
1200 out_len = handle_missing_map_mod(out_len, mod_node, options, map_off)?;
1201 mod_idx += 1;
1202 }
1203 (None, None) => break,
1204 }
1205 }
1206
1207 Ok(out_len)
1208}
1209
1210fn handle_missing_map_mod(
1211 out_len: usize,
1212 mod_node: &Node<'_>,
1213 options: EditOptions,
1214 map_off: usize,
1215) -> Result<usize, CborError> {
1216 match mod_node.terminal.as_ref() {
1217 Some(Terminal::Delete {
1218 mode: DeleteMode::IfPresent,
1219 }) => Ok(out_len),
1220 Some(
1221 Terminal::Delete {
1222 mode: DeleteMode::Require,
1223 }
1224 | Terminal::Set {
1225 mode: SetMode::ReplaceOnly,
1226 ..
1227 },
1228 ) => Err(missing_key(map_off)),
1229 Some(Terminal::Set { .. }) => out_len
1230 .checked_add(1)
1231 .ok_or_else(|| length_overflow(map_off)),
1232 None => {
1233 if options.create_missing_maps {
1234 match mod_node.children {
1235 Children::Keys(_) => out_len
1236 .checked_add(1)
1237 .ok_or_else(|| length_overflow(map_off)),
1238 _ => Err(err(ErrorCode::InvalidQuery, map_off)),
1239 }
1240 } else {
1241 Err(missing_key(map_off))
1242 }
1243 }
1244 }
1245}
1246
1247fn emit_map_entries<'a>(
1248 menc: &mut MapEncoder<'_>,
1249 map: crate::query::MapRef<'a>,
1250 mods: &[(Box<str>, Node<'a>)],
1251 options: EditOptions,
1252 map_off: usize,
1253) -> Result<(), CborError> {
1254 let mut mod_idx = 0usize;
1255 let mut iter = map.iter_encoded();
1256 let mut entry = next_map_entry_encoded(&mut iter)?;
1257
1258 while entry.is_some() || mod_idx < mods.len() {
1259 let cur_mod = mods.get(mod_idx);
1260 match (entry, cur_mod) {
1261 (Some((key, key_bytes, value)), Some((mod_key, mod_node))) => {
1262 match cmp_text_keys_canonical(key, mod_key.as_ref()) {
1263 Ordering::Less => {
1264 let value_ref = value;
1265 menc.entry_raw_key(key_bytes, |venc| venc.raw_value_ref(value_ref))?;
1266 entry = next_map_entry_encoded(&mut iter)?;
1267 }
1268 Ordering::Equal => {
1269 match mod_node.terminal.as_ref() {
1270 Some(Terminal::Delete { .. }) => {}
1271 Some(Terminal::Set {
1272 mode: SetMode::InsertOnly,
1273 ..
1274 }) => {
1275 return Err(err(ErrorCode::InvalidQuery, map_off));
1276 }
1277 Some(Terminal::Set { value, .. }) => {
1278 menc.entry_raw_key(key_bytes, |venc| write_new_value(venc, value))?;
1279 }
1280 None => {
1281 let value_ref = value;
1282 menc.entry_raw_key(key_bytes, |venc| {
1283 emit_value(venc, value_ref, mod_node, options)
1284 })?;
1285 }
1286 }
1287 mod_idx += 1;
1288 entry = next_map_entry_encoded(&mut iter)?;
1289 }
1290 Ordering::Greater => {
1291 emit_missing_map_entry(menc, mod_key.as_ref(), mod_node, options, map_off)?;
1292 mod_idx += 1;
1293 }
1294 }
1295 }
1296 (Some((_key, key_bytes, value)), None) => {
1297 let value_ref = value;
1298 menc.entry_raw_key(key_bytes, |venc| venc.raw_value_ref(value_ref))?;
1299 entry = next_map_entry_encoded(&mut iter)?;
1300 }
1301 (None, Some((mod_key, mod_node))) => {
1302 emit_missing_map_entry(menc, mod_key.as_ref(), mod_node, options, map_off)?;
1303 mod_idx += 1;
1304 }
1305 (None, None) => break,
1306 }
1307 }
1308
1309 Ok(())
1310}
1311
1312fn emit_missing_map_entry(
1313 menc: &mut MapEncoder<'_>,
1314 mod_key: &str,
1315 mod_node: &Node<'_>,
1316 options: EditOptions,
1317 map_off: usize,
1318) -> Result<(), CborError> {
1319 match mod_node.terminal.as_ref() {
1320 Some(Terminal::Delete {
1321 mode: DeleteMode::IfPresent,
1322 }) => Ok(()),
1323 Some(
1324 Terminal::Delete {
1325 mode: DeleteMode::Require,
1326 }
1327 | Terminal::Set {
1328 mode: SetMode::ReplaceOnly,
1329 ..
1330 },
1331 ) => Err(missing_key(map_off)),
1332 Some(Terminal::Set { value, .. }) => {
1333 menc.entry(mod_key, |venc| write_new_value(venc, value))
1334 }
1335 None => {
1336 if options.create_missing_maps {
1337 match mod_node.children {
1338 Children::Keys(_) => {
1339 menc.entry(mod_key, |venc| emit_created_value(venc, mod_node, options))
1340 }
1341 _ => Err(err(ErrorCode::InvalidQuery, map_off)),
1342 }
1343 } else {
1344 Err(missing_key(map_off))
1345 }
1346 }
1347 }
1348}
1349
1350fn emit_created_value<E: ValueEncoder>(
1351 enc: &mut E,
1352 node: &Node<'_>,
1353 options: EditOptions,
1354) -> Result<(), CborError> {
1355 if let Some(term) = node.terminal.as_ref() {
1356 return match term {
1357 Terminal::Set { value, .. } => write_new_value(enc, value),
1358 Terminal::Delete { .. } => Err(invalid_query()),
1359 };
1360 }
1361
1362 match node.children {
1363 Children::Keys(_) => emit_created_map(enc, node, options),
1364 _ => Err(invalid_query()),
1365 }
1366}
1367
1368fn emit_created_map<E: ValueEncoder>(
1369 enc: &mut E,
1370 node: &Node<'_>,
1371 options: EditOptions,
1372) -> Result<(), CborError> {
1373 let mods = node.key_children(0)?;
1374
1375 let mut out_len = 0usize;
1376 for (_key, child) in mods {
1377 match child.terminal.as_ref() {
1378 Some(Terminal::Delete { .. }) => return Err(invalid_query()),
1379 Some(Terminal::Set {
1380 mode: SetMode::ReplaceOnly,
1381 ..
1382 }) => return Err(missing_key(0)),
1383 Some(Terminal::Set { .. }) => {
1384 out_len = out_len.checked_add(1).ok_or_else(|| length_overflow(0))?;
1385 }
1386 None => match child.children {
1387 Children::Keys(_) if options.create_missing_maps => {
1388 out_len = out_len.checked_add(1).ok_or_else(|| length_overflow(0))?;
1389 }
1390 _ => return Err(missing_key(0)),
1391 },
1392 }
1393 }
1394
1395 enc.map(out_len, |menc| {
1396 for (key, child) in mods {
1397 match child.terminal.as_ref() {
1398 Some(Terminal::Delete { .. }) => return Err(invalid_query()),
1399 Some(Terminal::Set { value, .. }) => {
1400 menc.entry(key.as_ref(), |venc| write_new_value(venc, value))?;
1401 }
1402 None => {
1403 menc.entry(key.as_ref(), |venc| {
1404 emit_created_value(venc, child, options)
1405 })?;
1406 }
1407 }
1408 }
1409 Ok(())
1410 })
1411}
1412
1413fn next_map_entry<'a, I>(iter: &mut I) -> Result<Option<(&'a str, CborValueRef<'a>)>, CborError>
1414where
1415 I: Iterator<Item = Result<(&'a str, CborValueRef<'a>), CborError>>,
1416{
1417 match iter.next() {
1418 None => Ok(None),
1419 Some(Ok(v)) => Ok(Some(v)),
1420 Some(Err(e)) => Err(e),
1421 }
1422}
1423
1424type EncodedMapEntry<'a> = (&'a str, EncodedTextKey<'a>, CborValueRef<'a>);
1425
1426fn next_map_entry_encoded<'a, I>(iter: &mut I) -> Result<Option<EncodedMapEntry<'a>>, CborError>
1427where
1428 I: Iterator<Item = Result<EncodedMapEntry<'a>, CborError>>,
1429{
1430 match iter.next() {
1431 None => Ok(None),
1432 Some(Ok(v)) => Ok(Some(v)),
1433 Some(Err(e)) => Err(e),
1434 }
1435}
1436
1437impl<'a> CanonicalCborRef<'a> {
1439 #[must_use]
1441 pub const fn editor(self) -> Editor<'a> {
1442 Editor::new(self.root())
1443 }
1444
1445 pub fn edit<F>(self, f: F) -> Result<CanonicalCbor, CborError>
1451 where
1452 F: FnOnce(&mut Editor<'a>) -> Result<(), CborError>,
1453 {
1454 let mut editor = self.editor();
1455 f(&mut editor)?;
1456 editor.apply()
1457 }
1458}
1459
1460impl CanonicalCbor {
1462 #[must_use]
1464 pub fn editor(&self) -> Editor<'_> {
1465 Editor::new(self.root())
1466 }
1467
1468 pub fn edit<'a, F>(&'a self, f: F) -> Result<Self, CborError>
1474 where
1475 F: FnOnce(&mut Editor<'a>) -> Result<(), CborError>,
1476 {
1477 let mut editor = self.editor();
1478 f(&mut editor)?;
1479 editor.apply()
1480 }
1481}