willow_data_model/path/
mod.rs

1#[cfg(feature = "dev")]
2use arbitrary::{size_hint::and_all, Arbitrary, Error as ArbitraryError, Unstructured};
3use ufotofu_codec::Blame;
4
5// The `Path` struct is tested in `fuzz/path.rs`, `fuzz/path2.rs`, `fuzz/path3.rs`, `fuzz/path3.rs` by comparing against a non-optimised reference implementation.
6// Further, the `successor` and `greater_but_not_prefixed` methods of that reference implementation are tested in `fuzz/path_successor.rs` and friends, and `fuzz/path_successor_of_prefix.rs` and friends.
7
8use core::convert::AsRef;
9use core::fmt::Debug;
10use core::hash::Hash;
11use std::mem::size_of;
12
13use bytes::{BufMut, Bytes, BytesMut};
14
15mod builder;
16pub use builder::PathBuilder;
17
18mod representation;
19use representation::Representation;
20
21mod component;
22pub use component::*;
23
24mod codec; // Nothing to import, the file only provides trait implementations.
25pub use codec::{decode_path_extends_path, encode_path_extends_path};
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
28/// An error arising from trying to construct a invalid [`Path`] from valid components.
29pub enum InvalidPathError {
30    /// The path's total length in bytes is too large.
31    PathTooLong,
32    /// The path has too many components.
33    TooManyComponents,
34}
35
36impl core::fmt::Display for InvalidPathError {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        match self {
39            InvalidPathError::PathTooLong => {
40                write!(
41                    f,
42                    "Total length of a path in bytes exceeded the maximum path length"
43                )
44            }
45            InvalidPathError::TooManyComponents => {
46                write!(
47                    f,
48                    "Number of components of a path exceeded the maximum component count"
49                )
50            }
51        }
52    }
53}
54
55impl std::error::Error for InvalidPathError {}
56
57impl From<InvalidPathError> for Blame {
58    fn from(_value: InvalidPathError) -> Self {
59        Blame::TheirFault
60    }
61}
62
63/// An immutable Willow [path](https://willowprotocol.org/specs/data-model/index.html#Path). Thread-safe, cheap to clone, cheap to take prefixes of, expensive to append to (linear time complexity).
64///
65/// Enforces that each component has a length of at most `MCL` ([**m**ax\_**c**omponent\_**l**ength](https://willowprotocol.org/specs/data-model/index.html#max_component_length)), that each path has at most `MCC` ([**m**ax\_**c**omponent\_**c**count](https://willowprotocol.org/specs/data-model/index.html#max_component_count)) components, and that the total size in bytes of all components is at most `MPL` ([**m**ax\_**p**ath\_**l**ength](https://willowprotocol.org/specs/data-model/index.html#max_path_length)).
66#[derive(Clone)]
67pub struct Path<const MCL: usize, const MCC: usize, const MPL: usize> {
68    /// The data of the underlying path.
69    data: Bytes,
70    /// Number of components of the `data` to consider for this particular path (starting from the first component). Must be less than or equal to the total number of components.
71    /// This field enables cheap prefix creation by cloning the heap data (which is reference counted) and adjusting the `component_count`.
72    component_count: usize,
73}
74
75impl<const MCL: usize, const MCC: usize, const MPL: usize> Path<MCL, MCC, MPL> {
76    /// Returns an empty path, i.e., a path of zero components.
77    ///
78    /// #### Complexity
79    ///
80    /// Runs in `O(1)`, performs no allocations.
81    pub fn new_empty() -> Self {
82        PathBuilder::new(0, 0)
83            .expect("The empty path is legal for every choice of of MCL, MCC, and MPL.")
84            .build()
85    }
86
87    /// Creates a singleton path, i.e., a path of exactly one component.
88    ///
89    /// Copies the bytes of the component into an owned allocation on the heap.
90    ///
91    /// #### Complexity
92    ///
93    /// Runs in `O(n)`, where `n` is the length of the component. Performs a single allocation of `O(n)` bytes.
94    pub fn new_singleton(comp: Component<MCL>) -> Result<Self, InvalidPathError> {
95        let mut builder = PathBuilder::new(comp.len(), 1)?;
96        builder.append_component(comp);
97        Ok(builder.build())
98    }
99
100    /// Creates a path of known total length from an [`ExactSizeIterator`] of components.
101    ///
102    /// Copies the bytes of the components into an owned allocation on the heap.
103    ///
104    /// Panics if the claimed `total_length` does not match the sum of the lengths of all the components.
105    ///
106    /// #### Complexity
107    ///
108    /// Runs in `O(n)`, where `n` is the total length of the path in bytes. Performs a single allocation of `O(n)` bytes.
109    pub fn new_from_iter<'a, I>(total_length: usize, iter: &mut I) -> Result<Self, InvalidPathError>
110    where
111        I: ExactSizeIterator<Item = Component<'a, MCL>>,
112    {
113        let mut builder = PathBuilder::new(total_length, iter.len())?;
114
115        for component in iter {
116            builder.append_component(component);
117        }
118
119        Ok(builder.build())
120    }
121
122    /// Creates a path from a slice of components.
123    ///
124    /// Copies the bytes of the components into an owned allocation on the heap.
125    ///
126    /// #### Complexity
127    ///
128    /// Runs in `O(n)`, where `n` is the total length of the path in bytes. Performs a single allocation of `O(n)` bytes.
129    pub fn new_from_slice(components: &[Component<MCL>]) -> Result<Self, InvalidPathError> {
130        let mut total_length = 0;
131        for comp in components {
132            total_length += comp.len();
133        }
134
135        Self::new_from_iter(total_length, &mut components.iter().copied())
136    }
137
138    /// Creates a new path by appending a component to this one.
139    ///
140    /// Creates a fully separate copy of the new data on the heap; this function is not more efficient than constructing the new path from scratch.
141    ///
142    /// #### Complexity
143    ///
144    /// Runs in `O(n)`, where `n` is the total length of the new path in bytes. Performs a single allocation of `O(n)` bytes.
145    pub fn append(&self, comp: Component<MCL>) -> Result<Self, InvalidPathError> {
146        let mut builder =
147            PathBuilder::new(self.path_length() + comp.len(), self.component_count() + 1)?;
148
149        for component in self.components() {
150            builder.append_component(component);
151        }
152        builder.append_component(comp);
153
154        Ok(builder.build())
155    }
156
157    /// Creates a new path by appending a slice of components to this one.
158    ///
159    /// Creates a fully separate copy of the new data on the heap; this function is not more efficient than constructing the new path from scratch.
160    ///
161    /// #### Complexity
162    ///
163    /// Runs in `O(n)`, where `n` is the total length of the new path in bytes. Performs a single allocation of `O(n)` bytes.
164    pub fn append_slice(&self, components: &[Component<MCL>]) -> Result<Self, InvalidPathError> {
165        let mut total_length = self.path_length();
166        for comp in components {
167            total_length += comp.len();
168        }
169
170        let mut builder = PathBuilder::new_from_prefix(
171            total_length,
172            self.component_count() + components.len(),
173            self,
174            self.component_count(),
175        )?;
176
177        for additional_component in components {
178            builder.append_component(*additional_component);
179        }
180
181        Ok(builder.build())
182    }
183
184    /// Returns the number of components in this path.
185    ///
186    /// Guaranteed to be at most `MCC`.
187    ///
188    /// #### Complexity
189    ///
190    /// Runs in `O(1)`, performs no allocations.
191    pub fn component_count(&self) -> usize {
192        self.component_count
193    }
194
195    /// Returns whether this path has zero components.
196    ///
197    /// #### Complexity
198    ///
199    /// Runs in `O(1)`, performs no allocations.
200    pub fn is_empty(&self) -> bool {
201        self.component_count() == 0
202    }
203
204    /// Returns the sum of the lengths of all components in this path.
205    ///
206    /// Guaranteed to be at most `MCC`.
207    ///
208    /// #### Complexity
209    ///
210    /// Runs in `O(1)`, performs no allocations.
211    pub fn path_length(&self) -> usize {
212        self.path_length_of_prefix(self.component_count())
213    }
214
215    /// Returns the `i`-th [`Component`] of this path.
216    ///
217    /// #### Complexity
218    ///
219    /// Runs in `O(1)`, performs no allocations.
220    pub fn component(&self, i: usize) -> Option<Component<MCL>> {
221        if i < self.component_count {
222            Some(Representation::component(&self.data, i))
223        } else {
224            None
225        }
226    }
227
228    /// Returns an owned handle to the `i`-th [`Component`] of this path.
229    ///
230    /// #### Complexity
231    ///
232    /// Runs in `O(1)`, performs no allocations.
233    pub fn owned_component(&self, i: usize) -> Option<OwnedComponent<MCL>> {
234        if i < self.component_count {
235            let start = Representation::start_offset_of_component(&self.data, i);
236            let end = Representation::end_offset_of_component(&self.data, i);
237            Some(OwnedComponent(self.data.slice(start..end)))
238        } else {
239            None
240        }
241    }
242
243    /// Creates an iterator over the components of this path.
244    ///
245    /// Stepping the iterator takes `O(1)` time and performs no memory allocations.
246    ///
247    /// #### Complexity
248    ///
249    /// Runs in `O(1)`, performs no allocations.
250    pub fn components(
251        &self,
252    ) -> impl DoubleEndedIterator<Item = Component<MCL>> + ExactSizeIterator<Item = Component<MCL>>
253    {
254        self.suffix_components(0)
255    }
256
257    /// Creates an iterator over the components of this path, starting at the `i`-th component. If `i` is greater than or equal to the number of components, the iterator yields zero items.
258    ///
259    /// Stepping the iterator takes `O(1)` time and performs no memory allocations.
260    ///
261    /// #### Complexity
262    ///
263    /// Runs in `O(1)`, performs no allocations.
264    pub fn suffix_components(
265        &self,
266        i: usize,
267    ) -> impl DoubleEndedIterator<Item = Component<MCL>> + ExactSizeIterator<Item = Component<MCL>>
268    {
269        (i..self.component_count()).map(|i| {
270            self.component(i).unwrap() // Only `None` if `i >= self.component_count()`
271        })
272    }
273
274    /// Creates an iterator over owned handles to the components of this path.
275    ///
276    /// Stepping the iterator takes `O(1)` time and performs no memory allocations.
277    ///
278    /// #### Complexity
279    ///
280    /// Runs in `O(1)`, performs no allocations.
281    pub fn owned_components(
282        &self,
283    ) -> impl DoubleEndedIterator<Item = OwnedComponent<MCL>>
284           + ExactSizeIterator<Item = OwnedComponent<MCL>>
285           + '_ {
286        self.suffix_owned_components(0)
287    }
288
289    /// Creates an iterator over owned handles to the components of this path, starting at the `i`-th component. If `i` is greater than or equal to the number of components, the iterator yields zero items.
290    ///
291    /// Stepping the iterator takes `O(1)` time and performs no memory allocations.
292    ///
293    /// #### Complexity
294    ///
295    /// Runs in `O(1)`, performs no allocations.
296    pub fn suffix_owned_components(
297        &self,
298        i: usize,
299    ) -> impl DoubleEndedIterator<Item = OwnedComponent<MCL>>
300           + ExactSizeIterator<Item = OwnedComponent<MCL>>
301           + '_ {
302        (i..self.component_count()).map(|i| {
303            self.owned_component(i).unwrap() // Only `None` if `i >= self.component_count()`
304        })
305    }
306
307    /// Creates a new path that consists of the first `component_count` components. More efficient than creating a new [`Path`] from scratch.
308    ///
309    /// Returns `None` if `component_count` is greater than `self.get_component_count()`.
310    ///
311    /// #### Complexity
312    ///
313    /// Runs in `O(1)`, performs no allocations.
314    pub fn create_prefix(&self, component_count: usize) -> Option<Self> {
315        if component_count > self.component_count() {
316            None
317        } else {
318            Some(unsafe { self.create_prefix_unchecked(component_count) })
319        }
320    }
321
322    /// Creates a new path that consists of the first `component_count` components. More efficient than creating a new [`Path`] from scratch.
323    ///
324    /// #### Safety
325    ///
326    /// Undefined behaviour if `component_count` is greater than `self.component_count()`. May manifest directly, or at any later
327    /// function invocation that operates on the resulting [`Path`].
328    ///
329    /// #### Complexity
330    ///
331    /// Runs in `O(1)`, performs no allocations.
332    pub unsafe fn create_prefix_unchecked(&self, component_count: usize) -> Self {
333        Self {
334            data: self.data.clone(),
335            component_count,
336        }
337    }
338
339    /// Returns the sum of the lengths of the first `component_count` components in this path. More efficient than `path.create_prefix(component_count).path_length()`.
340    ///
341    /// Guaranteed to be at most `MCC`.
342    ///
343    /// #### Complexity
344    ///
345    /// Runs in `O(1)`, performs no allocations.
346    pub fn path_length_of_prefix(&self, component_count: usize) -> usize {
347        Representation::total_length(&self.data, component_count)
348    }
349
350    /// Creates an iterator over all prefixes of this path (including th empty path and the path itself).
351    ///
352    /// Stepping the iterator takes `O(1)` time and performs no memory allocations.
353    ///
354    /// #### Complexity
355    ///
356    /// Runs in `O(1)`, performs no allocations.
357    pub fn all_prefixes(&self) -> impl DoubleEndedIterator<Item = Self> + '_ {
358        (0..=self.component_count()).map(|i| {
359            unsafe {
360                self.create_prefix_unchecked(i) // safe to call for i <= self.component_count()
361            }
362        })
363    }
364
365    /// Tests whether this path is a prefix of the given path.
366    /// Paths are always a prefix of themselves, and the empty path is a prefix of every path.
367    ///
368    /// #### Complexity
369    ///
370    /// Runs in `O(n)`, where `n` is the total length of the shorter of the two paths. Performs no allocations.
371    pub fn is_prefix_of(&self, other: &Self) -> bool {
372        for (comp_a, comp_b) in self.components().zip(other.components()) {
373            if comp_a != comp_b {
374                return false;
375            }
376        }
377
378        self.component_count() <= other.component_count()
379    }
380
381    /// Tests whether this path is prefixed by the given path.
382    /// Paths are always a prefix of themselves.
383    ///
384    /// #### Complexity
385    ///
386    /// Runs in `O(n)`, where `n` is the total length of the shorter of the two paths. Performs no allocations.
387    pub fn is_prefixed_by(&self, other: &Self) -> bool {
388        other.is_prefix_of(self)
389    }
390
391    /// Tests whether this path is _related_ to the given path, that is, whether either one is a prefix of the other.
392    pub fn is_related(&self, other: &Self) -> bool {
393        self.is_prefix_of(other) || self.is_prefixed_by(other)
394    }
395
396    /// Returns the longest common prefix of this path and the given path.
397    ///
398    /// #### Complexity
399    ///
400    /// Runs in `O(n)`, where `n` is the total length of the shorter of the two paths. Performs a single allocation to create the return value.
401    pub fn longest_common_prefix(&self, other: &Self) -> Self {
402        let mut lcp_len = 0;
403
404        for (comp_a, comp_b) in self.components().zip(other.components()) {
405            if comp_a != comp_b {
406                break;
407            }
408
409            lcp_len += 1
410        }
411
412        self.create_prefix(lcp_len).unwrap() // zip ensures that lcp_len <= self.component_count()
413    }
414
415    /// Returns the least path which is strictly greater than `self`, or return `None` if `self` is the greatest possible path.
416    ///
417    /// #### Complexity
418    ///
419    /// Runs in `O(n)`, where `n` is the total length of the shorter of the two paths. Performs a single allocation to create the return value.
420    pub fn successor(&self) -> Option<Self> {
421        // If it is possible to append an empty component, then doing so yields the successor.
422        if let Ok(path) = self.append(Component::new_empty()) {
423            return Some(path);
424        }
425
426        // Otherwise, we try incrementing the final component. If that fails,
427        // we try to increment the second-to-final component, and so on.
428        // All components that come after the incremented component are discarded.
429        // If *no* component can be incremented, `self` is the maximal path and we return `None`.
430
431        for (i, component) in self.components().enumerate().rev() {
432            // It would be nice to call a `try_increment_component` function, but in order to avoid
433            // memory allocations, we write some lower-level but more efficient code.
434
435            // If it is possible to append a zero byte to a component, then doing so yields its successor.
436            if component.len() < MCL
437                && Representation::sum_of_lengths_for_component(self.data.as_ref(), i) < MPL
438            {
439                // We now know how to construct the path successor of `self`:
440                // Take the first `i` components (this *excludes* the current `component`),
441                // then append `component` with an additional zero byte at the end.
442                let mut buf = clone_prefix_and_lengthen_final_component(&self.data, i, 1);
443                buf.put_u8(0);
444
445                return Some(Path {
446                    data: buf.freeze(),
447                    component_count: i + 1,
448                });
449            }
450
451            // We **cannot** append a zero byte, so instead we check whether we can treat the component as a fixed-width integer and increment it. The only failure case is if that component consists of 255-bytes only.
452            let can_increment = !component.iter().all(|byte| *byte == 255);
453
454            // If we cannot increment, we go to the next iteration of the loop. But if we can, we can create a copy of the
455            // prefix on the first `i + 1` components, and mutate its backing memory in-place.
456            if can_increment {
457                let mut buf = clone_prefix_and_lengthen_final_component(&self.data, i, 0);
458
459                let start_component_offset =
460                    Representation::start_offset_of_component(buf.as_ref(), i);
461                let end_component_offset = Representation::end_offset_of_component(buf.as_ref(), i);
462                fixed_width_increment(
463                    &mut buf.as_mut()[start_component_offset..end_component_offset],
464                );
465
466                return Some(Path {
467                    data: buf.freeze(),
468                    component_count: i + 1,
469                });
470            }
471        }
472
473        // Failed to increment any component, so `self` is the maximal path.
474        None
475    }
476
477    /// Returns the least path that is strictly greater than `self` and which is not prefixed by `self`, or `None` if no such path exists.
478    ///
479    /// #### Complexity
480    ///
481    /// Runs in `O(n)`, where `n` is the total length of the shorter of the two paths. Performs a single allocation to create the return value.
482    pub fn greater_but_not_prefixed(&self) -> Option<Self> {
483        // We iterate through all components in reverse order. For each component, we check whether we can replace it by another cmponent that is strictly greater but not prefixed by the original component. If that is possible, we do replace it with the least such component and drop all later components. If that is impossible, we try again with the previous component. If this impossible for all components, then this function returns `None`.
484
485        for (i, component) in self.components().enumerate().rev() {
486            // If it is possible to append a zero byte to a component, then doing so yields its successor.
487            if component.len() < MCL
488                && Representation::sum_of_lengths_for_component(self.data.as_ref(), i) < MPL
489            {
490                let mut buf = clone_prefix_and_lengthen_final_component(&self.data, i, 1);
491                buf.put_u8(0);
492
493                return Some(Path {
494                    data: buf.freeze(),
495                    component_count: i + 1,
496                });
497            }
498
499            // Next, we check whether the i-th component can be changed into the least component that is greater but not prefixed by the original. If so, do that and cut off all later components.
500            let mut next_component_length = None;
501            for (j, comp_byte) in component.iter().enumerate().rev() {
502                if *comp_byte < 255 {
503                    next_component_length = Some(j + 1);
504                    break;
505                }
506            }
507
508            if let Some(next_component_length) = next_component_length {
509                // Yay, we can replace the i-th comopnent and then we are done.
510
511                let mut buf = clone_prefix_and_lengthen_final_component(&self.data, i, 0);
512                let length_of_prefix = Representation::sum_of_lengths_for_component(&buf, i);
513
514                // Update the length of the final component.
515                buf_set_final_component_length(
516                    buf.as_mut(),
517                    i,
518                    length_of_prefix - (component.len() - next_component_length),
519                );
520
521                // Increment the byte at position `next_component_length` of the final component.
522                let offset = Representation::start_offset_of_component(buf.as_ref(), i)
523                    + next_component_length
524                    - 1;
525                let byte = buf.as_ref()[offset]; // guaranteed < 255...
526                buf.as_mut()[offset] = byte + 1; // ... hence no overflow here.
527
528                return Some(Path {
529                    data: buf.freeze(),
530                    component_count: i + 1,
531                });
532            }
533        }
534
535        None
536    }
537}
538
539impl<const MCL: usize, const MCC: usize, const MPL: usize> PartialEq for Path<MCL, MCC, MPL> {
540    fn eq(&self, other: &Self) -> bool {
541        if self.component_count != other.component_count {
542            false
543        } else {
544            self.components().eq(other.components())
545        }
546    }
547}
548
549impl<const MCL: usize, const MCC: usize, const MPL: usize> Eq for Path<MCL, MCC, MPL> {}
550
551impl<const MCL: usize, const MCC: usize, const MPL: usize> Hash for Path<MCL, MCC, MPL> {
552    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
553        self.component_count.hash(state);
554
555        for comp in self.components() {
556            comp.hash(state);
557        }
558    }
559}
560
561impl<const MCL: usize, const MCC: usize, const MPL: usize> PartialOrd for Path<MCL, MCC, MPL> {
562    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
563        Some(self.cmp(other))
564    }
565}
566
567/// Compares paths lexicographically, since that is the path ordering that the Willow spec always uses.
568impl<const MCL: usize, const MCC: usize, const MPL: usize> Ord for Path<MCL, MCC, MPL> {
569    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
570        self.components().cmp(other.components())
571    }
572}
573
574impl<const MCL: usize, const MCC: usize, const MPL: usize> Debug for Path<MCL, MCC, MPL> {
575    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576        let data_vec: Vec<_> = self.components().collect();
577
578        f.debug_tuple("Path").field(&data_vec).finish()
579    }
580}
581
582#[cfg(feature = "dev")]
583impl<'a, const MCL: usize, const MCC: usize, const MPL: usize> Arbitrary<'a>
584    for Path<MCL, MCC, MPL>
585{
586    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, ArbitraryError> {
587        let mut total_length_in_bytes: usize = Arbitrary::arbitrary(u)?;
588        total_length_in_bytes %= MPL + 1;
589
590        let data: Box<[u8]> = Arbitrary::arbitrary(u)?;
591        total_length_in_bytes = core::cmp::min(total_length_in_bytes, data.len());
592
593        let mut num_components: usize = Arbitrary::arbitrary(u)?;
594        num_components %= MCC + 1;
595
596        if num_components == 0 {
597            total_length_in_bytes = 0;
598        }
599
600        let mut builder = PathBuilder::new(total_length_in_bytes, num_components).unwrap();
601
602        let mut length_total_so_far = 0;
603        for i in 0..num_components {
604            // Determine the length of the i-th component: randomly within some constraints for all but the final one. The final length is chosen to match the total_length_in_bytes.
605            let length_of_ith_component = if i + 1 == num_components {
606                if total_length_in_bytes - length_total_so_far > MCL {
607                    return Err(ArbitraryError::IncorrectFormat);
608                } else {
609                    total_length_in_bytes - length_total_so_far
610                }
611            } else {
612                // Any non-final component can take on a random length, ...
613                let mut component_length: usize = Arbitrary::arbitrary(u)?;
614                // ... except it must be at most the MCL, and...
615                component_length %= MCL + 1;
616                // ... the total length of all components must not exceed the total path length.
617                component_length = core::cmp::min(
618                    component_length,
619                    total_length_in_bytes - length_total_so_far,
620                );
621                component_length
622            };
623
624            builder.append_component(
625                Component::new(
626                    &data[length_total_so_far..length_total_so_far + length_of_ith_component],
627                )
628                .unwrap(),
629            );
630            length_total_so_far += length_of_ith_component;
631        }
632
633        Ok(builder.build())
634    }
635
636    #[inline]
637    fn size_hint(depth: usize) -> (usize, Option<usize>) {
638        (
639            and_all(&[
640                usize::size_hint(depth),
641                usize::size_hint(depth),
642                Box::<[u8]>::size_hint(depth),
643            ])
644            .0,
645            None,
646        )
647    }
648}
649
650/////////////////////////////////////////////////////////////////////
651// Helpers for efficiently creating successors.                    //
652// Efficiency warrants some low-level fiddling around here, sorry. //
653/////////////////////////////////////////////////////////////////////
654
655/// Creates a new BufMut that stores the heap encoding of the first i components of `original`, but increasing the length of the final component by `extra_capacity`. No data to fill that extra capacity is written into the buffer.
656fn clone_prefix_and_lengthen_final_component(
657    representation: &[u8],
658    i: usize,
659    extra_capacity: usize,
660) -> BytesMut {
661    let successor_path_length =
662        Representation::sum_of_lengths_for_component(representation, i) + extra_capacity;
663    let buf_capacity = size_of::<usize>() * (i + 2) + successor_path_length;
664    let mut buf = BytesMut::with_capacity(buf_capacity);
665
666    // Write the length of the successor path as the first usize.
667    buf.extend_from_slice(&(i + 1).to_ne_bytes());
668
669    // Next, copy the total path lengths for the first i prefixes.
670    buf.extend_from_slice(&representation[size_of::<usize>()..size_of::<usize>() * (i + 2)]);
671
672    // Now, write the length of the final component, which is one greater than before.
673    buf_set_final_component_length(buf.as_mut(), i, successor_path_length);
674
675    // Finally, copy the raw bytes of the first i+1 components.
676    buf.extend_from_slice(
677        &representation[Representation::start_offset_of_component(representation, 0)
678            ..Representation::start_offset_of_component(representation, i + 1)],
679    );
680
681    buf
682}
683
684// In a buffer that stores a path on the heap, set the sum of all component lengths for the i-th component, which must be the final component.
685fn buf_set_final_component_length(buf: &mut [u8], i: usize, new_sum_of_lengths: usize) {
686    let comp_len_start = Representation::start_offset_of_sum_of_lengths_for_component(i);
687    let comp_len_end = comp_len_start + size_of::<usize>();
688    buf[comp_len_start..comp_len_end].copy_from_slice(&new_sum_of_lengths.to_ne_bytes()[..]);
689}
690
691// Overflows to all zeroes if all bytes are 255.
692fn fixed_width_increment(buf: &mut [u8]) {
693    for byte_ref in buf.iter_mut().rev() {
694        if *byte_ref == 255 {
695            *byte_ref = 0;
696        } else {
697            *byte_ref += 1;
698            return;
699        }
700    }
701}