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}