use compact_u64::*;
use ufotofu::{ConsumeAtLeastError, codec_prelude::*};
use super::*;
async fn encode_from_iterator_of_components<'a, const MCL: usize, C, I>(
consumer: &mut C,
path_length: u64,
component_count: u64,
components: I,
) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8> + ?Sized,
I: Iterator<Item = &'a Component<MCL>>,
{
let mut header = 0;
write_tag(&mut header, 4, 0, path_length);
write_tag(&mut header, 4, 4, component_count);
consumer.consume_item(header).await?;
cu64_encode(path_length, 4, consumer).await?;
cu64_encode(component_count, 4, consumer).await?;
for (i, component) in components.enumerate() {
if i as u64 + 1 != component_count {
cu64_encode_standalone(component.len() as u64, consumer).await?;
}
consumer
.bulk_consume_full_slice(component.as_ref())
.await
.map_err(ConsumeAtLeastError::into_reason)?;
}
Ok(())
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> Encodable for Path<MCL, MCC, MPL> {
async fn encode<C>(&self, consumer: &mut C) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8> + ?Sized,
{
encode_from_iterator_of_components::<MCL, _, _>(
consumer,
self.total_length() as u64,
self.component_count() as u64,
self.components(),
)
.await
}
}
async fn decode_total_length_and_component_count_maybe_canonic<const CANONIC: bool, P>(
producer: &mut P,
) -> Result<(usize, usize), DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
let header = producer.produce_item().await?;
let total_length = if CANONIC {
cu64_decode_canonic(header, 4, 0, producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
} else {
cu64_decode(header, 4, 0, producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
};
let component_count = if CANONIC {
cu64_decode_canonic(header, 4, 4, producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
} else {
cu64_decode(header, 4, 4, producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
};
let total_length = Blame::u64_to_usize(total_length)?;
let component_count = Blame::u64_to_usize(component_count)?;
Ok((total_length, component_count))
}
async fn decode_components_maybe_canonic<
const CANONIC: bool,
const MCL: usize,
const MCC: usize,
const MPL: usize,
P,
>(
producer: &mut P,
mut builder: PathBuilder<MCL, MCC, MPL>,
initial_accumulated_component_length: usize,
remaining_component_count: usize,
expected_total_length: usize,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
let mut accumulated_component_length = initial_accumulated_component_length;
if remaining_component_count == 0 {
if expected_total_length > accumulated_component_length {
Err(DecodeError::Other(Blame::TheirFault))
} else {
Ok(builder.build())
}
} else {
for _ in 1..remaining_component_count {
let component_len = Blame::u64_to_usize(if CANONIC {
cu64_decode_canonic_standalone(producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
} else {
cu64_decode_standalone(producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
})?;
if component_len > MCL {
return Err(DecodeError::Other(Blame::TheirFault));
} else {
accumulated_component_length = accumulated_component_length
.checked_add(component_len)
.ok_or(DecodeError::Other(Blame::TheirFault))?;
builder
.append_component_from_bulk_producer(component_len, producer)
.await?;
}
}
let final_component_length = expected_total_length
.checked_sub(accumulated_component_length)
.ok_or(DecodeError::Other(Blame::TheirFault))?;
if final_component_length > MCL {
Err(DecodeError::Other(Blame::TheirFault))
} else {
builder
.append_component_from_bulk_producer(final_component_length, producer)
.await?;
Ok(builder.build())
}
}
}
async fn decode_maybe_canonic<
const CANONIC: bool,
const MCL: usize,
const MCC: usize,
const MPL: usize,
P,
>(
producer: &mut P,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
let (total_length, component_count) =
decode_total_length_and_component_count_maybe_canonic::<CANONIC, _>(producer).await?;
let builder = PathBuilder::new(total_length, component_count)
.map_err(|_| DecodeError::Other(Blame::TheirFault))?;
decode_components_maybe_canonic::<CANONIC, MCL, MCC, MPL, _>(
producer,
builder,
0,
component_count,
total_length,
)
.await
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> Decodable for Path<MCL, MCC, MPL> {
type ErrorReason = Blame;
async fn decode<P>(
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
decode_maybe_canonic::<false, MCL, MCC, MPL, _>(producer).await
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> DecodableCanonic
for Path<MCL, MCC, MPL>
{
type ErrorCanonic = Blame;
async fn decode_canonic<P>(
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
decode_maybe_canonic::<true, MCL, MCC, MPL, _>(producer).await
}
}
fn encoding_len_from_iterator_of_components<'a, const MCL: usize, I>(
path_length: u64,
component_count: usize,
components: I,
) -> usize
where
I: Iterator<Item = &'a Component<MCL>>,
{
let mut total_enc_len = 1;
total_enc_len += cu64_len_of_encoding(4, path_length);
total_enc_len += cu64_len_of_encoding(4, component_count as u64);
for (i, comp) in components.enumerate() {
if i + 1 < component_count {
total_enc_len += cu64_len_of_encoding(8, comp.len() as u64) + 1;
}
total_enc_len += comp.len();
}
total_enc_len
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> EncodableKnownLength
for Path<MCL, MCC, MPL>
{
fn len_of_encoding(&self) -> usize {
encoding_len_from_iterator_of_components::<MCL, _>(
self.total_length() as u64,
self.component_count(),
self.components(),
)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> RelativeEncodable<Path<MCL, MCC, MPL>>
for Path<MCL, MCC, MPL>
{
async fn relative_encode<Consumer>(
&self,
rel: &Path<MCL, MCC, MPL>,
consumer: &mut Consumer,
) -> Result<(), Consumer::Error>
where
Consumer: BulkConsumer<Item = u8> + ?Sized,
{
let lcp = self.longest_common_prefix(rel);
cu64_encode_standalone(lcp.component_count() as u64, consumer).await?;
let suffix_length = self.total_length() - lcp.total_length();
let suffix_component_count = self.component_count() - lcp.component_count();
encode_from_iterator_of_components::<MCL, _, _>(
consumer,
suffix_length as u64,
suffix_component_count as u64,
self.suffix_components(lcp.component_count()),
)
.await
}
fn can_be_encoded_relative_to(&self, _rel: &Path<MCL, MCC, MPL>) -> bool {
true
}
}
async fn relative_decode_maybe_canonic<
const CANONIC: bool,
const MCL: usize,
const MCC: usize,
const MPL: usize,
P,
>(
producer: &mut P,
rel: &Path<MCL, MCC, MPL>,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
let prefix_component_count = Blame::u64_to_usize(if CANONIC {
cu64_decode_canonic_standalone(producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
} else {
cu64_decode_standalone(producer)
.await
.map_err(|err| err.map_other(|_| Blame::TheirFault))?
})?;
let (suffix_length, suffix_component_count) =
decode_total_length_and_component_count_maybe_canonic::<CANONIC, _>(producer).await?;
if prefix_component_count > rel.component_count() {
return Err(DecodeError::Other(Blame::TheirFault));
}
let prefix_path_length = rel.total_length_of_prefix(prefix_component_count);
let total_length = prefix_path_length
.checked_add(suffix_length)
.ok_or(DecodeError::Other(Blame::TheirFault))?;
let total_component_count = prefix_component_count
.checked_add(suffix_component_count)
.ok_or(DecodeError::Other(Blame::TheirFault))?;
let builder = PathBuilder::new_from_prefix(
total_length,
total_component_count,
rel,
prefix_component_count,
)
.map_err(|_| DecodeError::Other(Blame::TheirFault))?;
let decoded = decode_components_maybe_canonic::<CANONIC, MCL, MCC, MPL, _>(
producer,
builder,
prefix_path_length,
suffix_component_count,
total_length,
)
.await?;
if CANONIC {
if prefix_component_count == rel.component_count() {
Ok(decoded)
} else if prefix_component_count == decoded.component_count() {
Ok(decoded)
} else {
if rel.component(prefix_component_count).unwrap()
== decoded.component(prefix_component_count).unwrap()
{
Err(DecodeError::Other(Blame::TheirFault))
} else {
Ok(decoded)
}
}
} else {
Ok(decoded)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> RelativeDecodable<Path<MCL, MCC, MPL>>
for Path<MCL, MCC, MPL>
{
type ErrorReason = Blame;
async fn relative_decode<P>(
rel: &Path<MCL, MCC, MPL>,
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
relative_decode_maybe_canonic::<false, MCL, MCC, MPL, _>(producer, rel).await
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeDecodableCanonic<Path<MCL, MCC, MPL>> for Path<MCL, MCC, MPL>
{
type ErrorCanonic = Blame;
async fn relative_decode_canonic<P>(
rel: &Path<MCL, MCC, MPL>,
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
relative_decode_maybe_canonic::<true, MCL, MCC, MPL, _>(producer, rel).await
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeEncodableKnownLength<Path<MCL, MCC, MPL>> for Path<MCL, MCC, MPL>
{
fn len_of_relative_encoding(&self, rel: &Path<MCL, MCC, MPL>) -> usize {
let lcp = self.longest_common_prefix(rel);
let path_len_of_suffix = self.total_length() - lcp.total_length();
let component_count_of_suffix = self.component_count() - lcp.component_count();
let mut total_enc_len = 0;
total_enc_len += cu64_len_of_encoding(8, lcp.component_count() as u64) + 1;
total_enc_len += encoding_len_from_iterator_of_components::<MCL, _>(
path_len_of_suffix as u64,
component_count_of_suffix,
self.suffix_components(lcp.component_count()),
);
total_enc_len
}
}
pub mod path_extends_path {
use super::*;
#[cfg(feature = "dev")]
use arbitrary::Arbitrary;
pub async fn encode_path_extends_path<const MCL: usize, const MCC: usize, const MPL: usize, C>(
path: &Path<MCL, MCC, MPL>,
prefix: &Path<MCL, MCC, MPL>,
consumer: &mut C,
) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8> + ?Sized,
{
if !path.is_prefixed_by(prefix) {
panic!("Tried to encode relative to a non-prefix with PathExtendsPath");
}
let extends_count = prefix.component_count();
let path_len = path.total_length() - prefix.total_length();
let diff = path.component_count() - extends_count;
encode_from_iterator_of_components(
consumer,
path_len as u64,
diff as u64,
path.suffix_components(extends_count),
)
.await?;
Ok(())
}
pub fn path_extends_path_encoding_len<const MCL: usize, const MCC: usize, const MPL: usize>(
path: &Path<MCL, MCC, MPL>,
prefix: &Path<MCL, MCC, MPL>,
) -> usize {
let prefix_count = prefix.component_count();
let path_len = path.total_length() - prefix.total_length();
let diff = path.component_count() - prefix_count;
encoding_len_from_iterator_of_components(
path_len as u64,
diff,
path.suffix_components(prefix_count),
)
}
pub async fn decode_path_extends_path<const MCL: usize, const MCC: usize, const MPL: usize, P>(
prefix: &Path<MCL, MCC, MPL>,
producer: &mut P,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
let suffix = Path::<MCL, MCC, MPL>::decode(producer)
.await
.map_err(|err| err.map_other(From::from))?;
let prefix_count = prefix.component_count();
let total_length = prefix.total_length() + suffix.total_length();
let total_count = prefix_count + suffix.component_count();
let mut path_builder =
PathBuilder::new_from_prefix(total_length, total_count, prefix, prefix_count)
.map_err(|_err| DecodeError::Other(Blame::TheirFault))?;
for component in suffix.components() {
path_builder.append_component(component);
}
Ok(path_builder.build())
}
pub async fn decode_path_extends_path_canonic<
const MCL: usize,
const MCC: usize,
const MPL: usize,
P,
>(
prefix: &Path<MCL, MCC, MPL>,
producer: &mut P,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8> + ?Sized,
{
let suffix = Path::<MCL, MCC, MPL>::decode_canonic(producer)
.await
.map_err(|err| err.map_other(From::from))?;
let prefix_count = prefix.component_count();
let total_length = prefix.total_length() + suffix.total_length();
let total_count = prefix_count + suffix.component_count();
let mut path_builder =
PathBuilder::new_from_prefix(total_length, total_count, prefix, prefix_count)
.map_err(|_err| DecodeError::Other(Blame::TheirFault))?;
for component in suffix.components() {
path_builder.append_component(component);
}
Ok(path_builder.build())
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, Debug)]
#[cfg_attr(feature = "dev", derive(Arbitrary))]
pub struct CodecPathExtendsPath<const MCL: usize, const MCC: usize, const MPL: usize>(
pub Path<MCL, MCC, MPL>,
);
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeEncodable<Path<MCL, MCC, MPL>> for CodecPathExtendsPath<MCL, MCC, MPL>
{
async fn relative_encode<C>(
&self,
rel: &Path<MCL, MCC, MPL>,
consumer: &mut C,
) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8> + ?Sized,
{
encode_path_extends_path(&self.0, rel, consumer).await
}
fn can_be_encoded_relative_to(&self, rel: &Path<MCL, MCC, MPL>) -> bool {
rel.is_prefix_of(&self.0)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeEncodableKnownLength<Path<MCL, MCC, MPL>> for CodecPathExtendsPath<MCL, MCC, MPL>
{
fn len_of_relative_encoding(&self, rel: &Path<MCL, MCC, MPL>) -> usize {
path_extends_path_encoding_len(&self.0, rel)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeDecodable<Path<MCL, MCC, MPL>> for CodecPathExtendsPath<MCL, MCC, MPL>
{
type ErrorReason = Blame;
async fn relative_decode<P>(
rel: &Path<MCL, MCC, MPL>,
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
where
P: BulkProducer<Item = u8> + ?Sized,
Self: Sized,
{
Ok(Self(decode_path_extends_path(rel, producer).await?))
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeDecodableCanonic<Path<MCL, MCC, MPL>> for CodecPathExtendsPath<MCL, MCC, MPL>
{
type ErrorCanonic = Blame;
async fn relative_decode_canonic<P>(
rel: &Path<MCL, MCC, MPL>,
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
where
P: BulkProducer<Item = u8> + ?Sized,
Self: Sized,
{
Ok(Self(decode_path_extends_path_canonic(rel, producer).await?))
}
}
}