use ufotofu::{BulkConsumer, BulkProducer};
use ufotofu_codec::{
Blame, Decodable, DecodableCanonic, DecodableSync, DecodeError, Encodable, EncodableKnownSize,
EncodableSync, RelativeDecodable, RelativeDecodableCanonic, RelativeDecodableSync,
RelativeEncodable, RelativeEncodableKnownSize, RelativeEncodableSync,
};
use compact_u64::*;
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>,
I: Iterator<Item = Component<'a, MCL>>,
{
let path_length_tag = Tag::min_tag(path_length, TagWidth::four());
let component_count_tag = Tag::min_tag(component_count, TagWidth::four());
let first_byte = path_length_tag.data_at_offset(0) | component_count_tag.data_at_offset(4);
consumer.consume(first_byte).await?;
let total_bytes_bytes = CompactU64(path_length);
total_bytes_bytes
.relative_encode(consumer, &path_length_tag.encoding_width())
.await?;
let component_count_bytes = CompactU64(component_count);
component_count_bytes
.relative_encode(consumer, &component_count_tag.encoding_width())
.await?;
for (i, component) in components.enumerate() {
if i as u64 + 1 != component_count {
CompactU64(component.len() as u64).encode(consumer).await?;
}
consumer
.bulk_consume_full_slice(component.as_ref())
.await
.map_err(|err| err.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>,
{
encode_from_iterator_of_components::<MCL, _, _>(
consumer,
self.path_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>,
{
let first_byte = producer.produce_item().await?;
let path_length_tag = Tag::from_raw(first_byte, TagWidth::four(), 0);
let component_count_tag = Tag::from_raw(first_byte, TagWidth::four(), 4);
let total_length = relative_decode_cu64::<CANONIC, _>(producer, &path_length_tag).await?;
let component_count =
relative_decode_cu64::<CANONIC, _>(producer, &component_count_tag).await?;
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>,
{
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(decode_cu64::<CANONIC, _>(producer).await?)?;
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>,
{
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>,
Self: 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>,
Self: 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 = Component<'a, MCL>>,
{
let mut total_enc_len = 1;
total_enc_len += EncodingWidth::min_width(path_length, TagWidth::four()).as_usize();
total_enc_len += EncodingWidth::min_width(component_count as u64, TagWidth::four()).as_usize();
for (i, comp) in components.enumerate() {
if i + 1 < component_count {
total_enc_len += CompactU64(comp.len() as u64).len_of_encoding();
}
total_enc_len += comp.len();
}
total_enc_len
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> EncodableKnownSize
for Path<MCL, MCC, MPL>
{
fn len_of_encoding(&self) -> usize {
encoding_len_from_iterator_of_components::<MCL, _>(
self.path_length() as u64,
self.component_count(),
self.components(),
)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize> EncodableSync for Path<MCL, MCC, MPL> {}
impl<const MCL: usize, const MCC: usize, const MPL: usize> DecodableSync for Path<MCL, MCC, MPL> {}
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,
consumer: &mut Consumer,
reference: &Path<MCL, MCC, MPL>,
) -> Result<(), Consumer::Error>
where
Consumer: BulkConsumer<Item = u8>,
{
let lcp = self.longest_common_prefix(reference);
CompactU64(lcp.component_count() as u64)
.encode(consumer)
.await?;
let suffix_length = self.path_length() - lcp.path_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
}
}
async fn relative_decode_maybe_canonic<
const CANONIC: bool,
const MCL: usize,
const MCC: usize,
const MPL: usize,
P,
>(
producer: &mut P,
r: &Path<MCL, MCC, MPL>,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8>,
{
let prefix_component_count = Blame::u64_to_usize(decode_cu64::<CANONIC, _>(producer).await?)?;
let (suffix_length, suffix_component_count) =
decode_total_length_and_component_count_maybe_canonic::<CANONIC, _>(producer).await?;
if prefix_component_count > r.component_count() {
return Err(DecodeError::Other(Blame::TheirFault));
}
let prefix_path_length = r.path_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,
r,
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 == r.component_count() {
Ok(decoded)
} else if prefix_component_count == decoded.component_count() {
Ok(decoded)
} else {
if r.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>, Blame> for Path<MCL, MCC, MPL>
{
async fn relative_decode<P>(
producer: &mut P,
r: &Path<MCL, MCC, MPL>,
) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8>,
Self: Sized,
{
relative_decode_maybe_canonic::<false, MCL, MCC, MPL, _>(producer, r).await
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeDecodableCanonic<Path<MCL, MCC, MPL>, Blame, Blame> for Path<MCL, MCC, MPL>
{
async fn relative_decode_canonic<P>(
producer: &mut P,
r: &Path<MCL, MCC, MPL>,
) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8>,
Self: Sized,
{
relative_decode_maybe_canonic::<true, MCL, MCC, MPL, _>(producer, r).await
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeEncodableKnownSize<Path<MCL, MCC, MPL>> for Path<MCL, MCC, MPL>
{
fn relative_len_of_encoding(&self, r: &Path<MCL, MCC, MPL>) -> usize {
let lcp = self.longest_common_prefix(r);
let path_len_of_suffix = self.path_length() - lcp.path_length();
let component_count_of_suffix = self.component_count() - lcp.component_count();
let mut total_enc_len = 0;
total_enc_len += CompactU64(lcp.component_count() as u64).len_of_encoding();
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
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeEncodableSync<Path<MCL, MCC, MPL>> for Path<MCL, MCC, MPL>
{
}
impl<const MCL: usize, const MCC: usize, const MPL: usize>
RelativeDecodableSync<Path<MCL, MCC, MPL>, Blame> for Path<MCL, MCC, MPL>
{
}
pub async fn relative_decode_cu64<const CANONIC: bool, P>(
producer: &mut P,
tag: &Tag,
) -> Result<u64, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8>,
{
if CANONIC {
Ok(CompactU64::relative_decode_canonic(producer, tag)
.await
.map_err(|err| DecodeError::map_other(err, |_| Blame::TheirFault))?
.0)
} else {
Ok(CompactU64::relative_decode(producer, tag)
.await
.map_err(|err| DecodeError::map_other(err, |_| Blame::TheirFault))?
.0)
}
}
pub async fn decode_cu64<const CANONIC: bool, P>(
producer: &mut P,
) -> Result<u64, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8>,
{
if CANONIC {
Ok(CompactU64::decode_canonic(producer)
.await
.map_err(|err| DecodeError::map_other(err, |_| Blame::TheirFault))?
.0)
} else {
Ok(CompactU64::decode(producer)
.await
.map_err(|err| DecodeError::map_other(err, |_| Blame::TheirFault))?
.0)
}
}
pub async fn encode_path_extends_path<const MCL: usize, const MCC: usize, const MPL: usize, C>(
consumer: &mut C,
path: &Path<MCL, MCC, MPL>,
extends: &Path<MCL, MCC, MPL>,
) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8>,
{
if !path.is_prefixed_by(extends) {
panic!("Tried to encode with PathExtendsPath with a path that does not extend another path")
}
let extends_count = extends.component_count();
let path_len = path.path_length() - extends.path_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 async fn decode_path_extends_path<const MCL: usize, const MCC: usize, const MPL: usize, P>(
producer: &mut P,
prefix: &Path<MCL, MCC, MPL>,
) -> Result<Path<MCL, MCC, MPL>, DecodeError<P::Final, P::Error, Blame>>
where
P: BulkProducer<Item = u8>,
{
let suffix = Path::<MCL, MCC, MPL>::decode(producer)
.await
.map_err(DecodeError::map_other_from)?;
let prefix_count = prefix.component_count();
let total_length = prefix.path_length() + suffix.path_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())
}