use core::mem::size_of;
use bytes::{BufMut, BytesMut};
use ufotofu::codec_prelude::*;
use crate::prelude::*;
use super::Representation;
#[derive(Debug)]
pub struct PathBuilder<const MCL: usize, const MCC: usize, const MPL: usize> {
bytes: BytesMut, initialised_components: usize, target_length: usize, }
impl<const MCL: usize, const MCC: usize, const MPL: usize> PathBuilder<MCL, MCC, MPL> {
pub fn new(
total_length: usize,
component_count: usize,
) -> Result<Self, PathFromComponentsError> {
if total_length > MPL {
return Err(PathFromComponentsError::PathTooLong);
}
if component_count > MCC {
return Err(PathFromComponentsError::TooManyComponents);
}
let mut buf = BytesMut::with_capacity(Representation::allocation_size(
total_length,
component_count,
));
buf.extend_from_slice(&(component_count.to_ne_bytes())[..]);
buf.put_bytes(0, component_count * size_of::<usize>());
Ok(Self {
bytes: buf,
initialised_components: 0,
target_length: total_length,
})
}
pub fn new_from_prefix(
target_total_length: usize,
target_component_count: usize,
reference: &Path<MCL, MCC, MPL>,
prefix_component_count: usize,
) -> Result<Self, PathFromComponentsError> {
let mut builder = Self::new(target_total_length, target_component_count)?;
assert!(reference.component_count() >= prefix_component_count);
match prefix_component_count.checked_sub(1) {
None => return Ok(builder),
Some(index_of_final_component) => {
if reference.first_component == 0 {
let accumulated_component_lengths_start =
Representation::start_offset_of_sum_of_lengths_for_component(0);
let accumulated_component_lengths_end =
Representation::start_offset_of_sum_of_lengths_for_component(
index_of_final_component + 1,
);
builder.bytes.as_mut()
[accumulated_component_lengths_start..accumulated_component_lengths_end]
.copy_from_slice(
&reference.data[accumulated_component_lengths_start
..accumulated_component_lengths_end],
);
} else {
let mut start_of_component_length =
Representation::start_offset_of_sum_of_lengths_for_component(0);
for i in 0..prefix_component_count {
let end_of_component_length =
start_of_component_length + size_of::<usize>();
builder.bytes.as_mut()[start_of_component_length..end_of_component_length]
.copy_from_slice(
&reference.total_length_of_prefix(i + 1).to_ne_bytes(),
);
start_of_component_length = end_of_component_length;
}
}
let start_of_prefix_components = Representation::start_offset_of_component(
&reference.data,
reference.first_component,
);
let end_of_prefix_components = Representation::end_offset_of_component(
&reference.data,
reference.first_component + index_of_final_component,
);
builder.bytes.extend_from_slice(
&reference.data[start_of_prefix_components..end_of_prefix_components],
);
builder.initialised_components = prefix_component_count;
}
}
Ok(builder)
}
pub fn append_component(&mut self, component: &Component<MCL>) {
let total_length_so_far = match self.initialised_components.checked_sub(1) {
Some(i) => Representation::sum_of_lengths_for_component(&self.bytes, i),
None => 0,
};
let acc_length = component.as_ref().len() + total_length_so_far;
let start = Representation::start_offset_of_sum_of_lengths_for_component(
self.initialised_components,
);
let end = start + size_of::<usize>();
self.bytes.as_mut()[start..end].copy_from_slice(&acc_length.to_ne_bytes()[..]);
self.bytes.extend_from_slice(component.as_ref());
self.initialised_components += 1;
}
pub fn append_slice(&mut self, component: &[u8]) -> Result<(), InvalidComponentError> {
self.append_component(Component::new(component)?);
Ok(())
}
pub async fn append_component_from_bulk_producer<P>(
&mut self,
component_length: usize,
p: &mut P,
) -> Result<(), DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
assert!(component_length <= MCL);
let total_length_so_far = match self.initialised_components.checked_sub(1) {
Some(i) => Representation::sum_of_lengths_for_component(&self.bytes, i),
None => 0,
};
let acc_length = component_length + total_length_so_far;
let start = Representation::start_offset_of_sum_of_lengths_for_component(
self.initialised_components,
);
let end = start + size_of::<usize>();
self.bytes.as_mut()[start..end].copy_from_slice(&acc_length.to_ne_bytes()[..]);
if component_length == 0 {
self.initialised_components += 1;
return Ok(());
}
let mut produced_so_far = 0;
while produced_so_far < component_length {
if let Right(fin) = p
.expose_items_sync(|items| {
let remaining_len =
core::cmp::min(items.len(), component_length - produced_so_far);
self.bytes.extend_from_slice(&items[..remaining_len]);
produced_so_far += remaining_len;
(remaining_len, ())
})
.await?
{
return Err(DecodeError::UnexpectedEndOfInput(fin));
}
}
self.initialised_components += 1;
Ok(())
}
pub fn build(self) -> Path<MCL, MCC, MPL> {
assert_eq!(
self.initialised_components,
Representation::component_count(self.bytes.as_ref())
);
assert_eq!(
self.target_length,
self.total_length(),
"Expected a target length of {}, but got an actual total_length of {}\nRaw representation:{:?}",
self.target_length,
self.total_length(),
self.bytes
);
Path {
data: self.bytes.freeze(),
component_count: self.initialised_components,
first_component: 0,
}
}
pub fn total_length(&self) -> usize {
Representation::total_length(&self.bytes, self.initialised_components)
}
pub fn component_count(&self) -> usize {
self.initialised_components
}
}