Skip to main content

sacp_cbor/
edit.rs

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/// Mode for map set operations.
49#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum SetMode {
52    /// Insert or replace the target key (default).
53    Upsert,
54    /// Insert only; error if the key already exists.
55    InsertOnly,
56    /// Replace only; error if the key is missing.
57    ReplaceOnly,
58}
59
60/// Mode for delete operations.
61#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum DeleteMode {
64    /// Require the key to exist (default).
65    Require,
66    /// Ignore missing keys.
67    IfPresent,
68}
69
70/// Array splice position.
71#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum ArrayPos {
74    /// Splice at the given index.
75    At(usize),
76    /// Splice at the end of the array.
77    End,
78}
79
80/// Edit behavior options.
81#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
83pub struct EditOptions {
84    /// Allow creating missing map containers when descending into absent keys.
85    pub create_missing_maps: bool,
86}
87
88/// Incremental editor for canonical CBOR bytes.
89#[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    /// Returns mutable access to editor options.
109    pub fn options_mut(&mut self) -> &mut EditOptions {
110        &mut self.options
111    }
112
113    /// Start building an array splice at `array_path`.
114    ///
115    /// `array_path` must resolve to an array at apply time. Indices are interpreted
116    /// against the original array (before edits).
117    ///
118    /// # Errors
119    ///
120    /// Returns `CborError` on invalid paths or malformed splice parameters.
121    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    /// Append a value to the end of an array.
141    ///
142    /// # Errors
143    ///
144    /// Returns `CborError` for invalid paths or encoding failure.
145    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    /// Append an encoded value to the end of an array.
156    ///
157    /// # Errors
158    ///
159    /// Returns `CborError` for invalid paths or encoding failure.
160    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    /// Set or replace the value at `path`.
170    ///
171    /// For map keys this performs an upsert; for arrays it replaces the element.
172    ///
173    /// # Errors
174    ///
175    /// Returns `CborError` on invalid paths, conflicts, or encoding failure.
176    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    /// Insert an entry at `path`.
185    ///
186    /// For map keys this inserts the key. For arrays this inserts before the index.
187    ///
188    /// # Errors
189    ///
190    /// Returns an error if the key already exists or if the path is invalid.
191    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    /// Replace an entry at `path`.
200    ///
201    /// For map keys this replaces the key. For arrays this replaces the element.
202    ///
203    /// # Errors
204    ///
205    /// Returns an error if the key is missing or if the path is invalid.
206    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    /// Set a value from an existing canonical value reference without re-encoding.
215    ///
216    /// # Errors
217    ///
218    /// Returns `CborError` on invalid paths or conflicts.
219    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    /// Encode a value using a `Encoder` and set it at `path`.
234    ///
235    /// # Errors
236    ///
237    /// Returns `CborError` if encoding fails or if the encoded bytes are not a single CBOR item.
238    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    /// Delete an entry at `path`.
253    ///
254    /// For map keys this deletes the key. For arrays this deletes the element.
255    ///
256    /// # Errors
257    ///
258    /// Returns an error if the key is missing or if the path is invalid.
259    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    /// Delete an entry at `path` if present.
269    ///
270    /// For map keys this ignores missing keys. For arrays this ignores out-of-bounds indices.
271    ///
272    /// # Errors
273    ///
274    /// Returns an error for invalid paths or conflicts.
275    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    /// Apply all recorded edits and return updated canonical CBOR.
285    ///
286    /// # Errors
287    ///
288    /// Returns an error if any edit is invalid, conflicts, or fails during encoding.
289    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/// Encodes a single canonical CBOR value into an `Encoder`.
357#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
358pub trait EditEncode<'a>: sealed::Sealed {
359    /// Encode this value into a canonical CBOR item ready for patching.
360    ///
361    /// # Errors
362    ///
363    /// Returns `CborError` if encoding fails or produces invalid canonical CBOR.
364    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/// Builder for an array splice edit.
491#[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    /// Insert a value into the splice.
503    ///
504    /// # Errors
505    ///
506    /// Returns `CborError` if encoding fails.
507    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    /// Insert a raw canonical value reference into the splice.
515    ///
516    /// # Errors
517    ///
518    /// Returns `CborError` on allocation failure.
519    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    /// Insert a value encoded via `Encoder` into the splice.
526    ///
527    /// # Errors
528    ///
529    /// Returns `CborError` if encoding fails.
530    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    /// Finalize and record the splice.
541    ///
542    /// # Errors
543    ///
544    /// Returns `CborError` for invalid paths or conflicts.
545    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)]
609/// Encoded edit value used by the editor.
610pub struct EditValue<'a>(EditValueInner<'a>);
611
612#[derive(Debug, Clone)]
613enum EditValueInner<'a> {
614    /// Splice an existing canonical value reference.
615    Raw(CborValueRef<'a>),
616    /// Splice canonical bytes by reference.
617    BytesRef(CanonicalCborRef<'a>),
618    /// Splice owned canonical bytes.
619    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
1437/// Adds editing methods to `CanonicalCborRef`.
1438impl<'a> CanonicalCborRef<'a> {
1439    /// Create a `Editor` for this message.
1440    #[must_use]
1441    pub const fn editor(self) -> Editor<'a> {
1442        Editor::new(self.root())
1443    }
1444
1445    /// Apply a sequence of edits atomically.
1446    ///
1447    /// # Errors
1448    ///
1449    /// Returns `CborError` if any edit fails or the patch is invalid.
1450    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
1460/// Adds editing methods to `CanonicalCbor`.
1461impl CanonicalCbor {
1462    /// Create a `Editor` for this message.
1463    #[must_use]
1464    pub fn editor(&self) -> Editor<'_> {
1465        Editor::new(self.root())
1466    }
1467
1468    /// Apply a sequence of edits atomically.
1469    ///
1470    /// # Errors
1471    ///
1472    /// Returns `CborError` if any edit fails or the patch is invalid.
1473    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}