willow_data_model/path/
builder.rs1use core::cmp::min;
2use core::mem::size_of;
3
4use bytes::{BufMut, BytesMut};
5use either::Either::*;
6use ufotofu::BulkProducer;
7use ufotofu_codec::{Blame, DecodeError};
8
9use super::{Component, InvalidPathError, Path, Representation};
10
11pub struct PathBuilder<const MCL: usize, const MCC: usize, const MPL: usize> {
15 bytes: BytesMut, initialised_components: usize, target_length: usize, }
19
20impl<const MCL: usize, const MCC: usize, const MPL: usize> PathBuilder<MCL, MCC, MPL> {
21 pub fn new(total_length: usize, component_count: usize) -> Result<Self, InvalidPathError> {
24 if total_length > MPL {
25 return Err(InvalidPathError::PathTooLong);
26 }
27
28 if component_count > MCC {
29 return Err(InvalidPathError::TooManyComponents);
30 }
31
32 let mut buf = BytesMut::with_capacity(Representation::allocation_size(
34 total_length,
35 component_count,
36 ));
37
38 buf.extend_from_slice(&(component_count.to_ne_bytes())[..]);
40
41 buf.put_bytes(0, component_count * size_of::<usize>());
43
44 Ok(Self {
45 bytes: buf,
46 initialised_components: 0,
47 target_length: total_length,
48 })
49 }
50
51 pub fn new_from_prefix(
54 target_total_length: usize,
55 target_component_count: usize,
56 reference: &Path<MCL, MCC, MPL>,
57 prefix_component_count: usize,
58 ) -> Result<Self, InvalidPathError> {
59 let mut builder = Self::new(target_total_length, target_component_count)?;
60
61 assert!(reference.component_count() >= prefix_component_count);
62
63 match prefix_component_count.checked_sub(1) {
65 None => return Ok(builder),
66 Some(index_of_final_component) => {
67 let accumulated_component_lengths_start =
69 Representation::start_offset_of_sum_of_lengths_for_component(0);
70 let accumulated_component_lengths_end =
71 Representation::start_offset_of_sum_of_lengths_for_component(
72 index_of_final_component + 1,
73 );
74 builder.bytes.as_mut()
75 [accumulated_component_lengths_start..accumulated_component_lengths_end]
76 .copy_from_slice(
77 &reference.data[accumulated_component_lengths_start
78 ..accumulated_component_lengths_end],
79 );
80
81 let components_start_in_prefix =
82 Representation::start_offset_of_component(&reference.data, 0);
83 let components_end_in_prefix = Representation::end_offset_of_component(
84 &reference.data,
85 index_of_final_component,
86 );
87 builder.bytes.extend_from_slice(
88 &reference.data[components_start_in_prefix..components_end_in_prefix],
89 );
90
91 builder.initialised_components = prefix_component_count;
93 }
94 }
95
96 Ok(builder)
107 }
108
109 pub async fn append_component_from_bulk_producer<P>(
111 &mut self,
112 component_length: usize,
113 p: &mut P,
114 ) -> Result<(), DecodeError<P::Final, P::Error, Blame>>
115 where
116 P: BulkProducer<Item = u8>,
117 {
118 assert!(component_length <= MCL);
119
120 let total_length_so_far = match self.initialised_components.checked_sub(1) {
122 Some(i) => Representation::sum_of_lengths_for_component(&self.bytes, i),
123 None => 0,
124 };
125 let acc_length = component_length + total_length_so_far;
126
127 let start = Representation::start_offset_of_sum_of_lengths_for_component(
129 self.initialised_components,
130 );
131 let end = start + size_of::<usize>();
132 self.bytes.as_mut()[start..end].copy_from_slice(&acc_length.to_ne_bytes()[..]);
133
134 if component_length == 0 {
136 self.initialised_components += 1;
138 return Ok(());
139 }
140
141 let mut produced_so_far = 0;
143 while produced_so_far < component_length {
144 match p.expose_items().await? {
146 Right(fin) => return Err(DecodeError::UnexpectedEndOfInput(fin)),
147 Left(data) => {
148 let remaining_len = min(data.len(), component_length - produced_so_far);
149 self.bytes.extend_from_slice(&data[..remaining_len]);
150 p.consider_produced(remaining_len).await?;
151 produced_so_far += remaining_len;
152 }
153 }
154 }
155
156 self.initialised_components += 1;
158
159 Ok(())
160 }
161
162 pub fn append_component(&mut self, component: Component<MCL>) {
164 let total_length_so_far = match self.initialised_components.checked_sub(1) {
166 Some(i) => Representation::sum_of_lengths_for_component(&self.bytes, i),
167 None => 0,
168 };
169 let acc_length = component.len() + total_length_so_far;
170
171 let start = Representation::start_offset_of_sum_of_lengths_for_component(
173 self.initialised_components,
174 );
175 let end = start + size_of::<usize>();
176 self.bytes.as_mut()[start..end].copy_from_slice(&acc_length.to_ne_bytes()[..]);
177
178 self.bytes.extend_from_slice(component.as_ref());
180
181 self.initialised_components += 1;
183 }
184
185 pub fn build(self) -> Path<MCL, MCC, MPL> {
189 assert_eq!(
191 self.initialised_components,
192 Representation::component_count(self.bytes.as_ref())
193 );
194
195 assert_eq!(
196 self.target_length,
197 Representation::total_length(&self.bytes, self.initialised_components),
198 "Expected a target length of {}, but got an actual total_length of {}\nRaw representation:{:?}",
199 self.target_length,
200 Representation::total_length(&self.bytes, self.initialised_components),
201 self.bytes
202 );
203
204 Path {
205 data: self.bytes.freeze(),
206 component_count: self.initialised_components,
207 }
208 }
209}