From 5d64d373495d010ce4b2a5e16a6f3be7e87d5a2c Mon Sep 17 00:00:00 2001 From: Sam Gwilym Date: Wed, 31 Jul 2024 14:35:35 +0100 Subject: [PATCH] syncify data-model --- data-model/src/encoding/bytes.rs | 37 +- data-model/src/encoding/compact_width.rs | 103 +- data-model/src/encoding/parameters.rs | 26 + data-model/src/encoding/parameters_sync.rs | 33 +- data-model/src/encoding/relativity.rs | 2150 ++++++++++---------- data-model/src/encoding/unsigned_int.rs | 236 ++- data-model/src/entry.rs | 103 +- fuzz/src/encode.rs | 3 +- 8 files changed, 1393 insertions(+), 1298 deletions(-) diff --git a/data-model/src/encoding/bytes.rs b/data-model/src/encoding/bytes.rs index 5092916..7af61b1 100644 --- a/data-model/src/encoding/bytes.rs +++ b/data-model/src/encoding/bytes.rs @@ -1,19 +1,28 @@ -use either::Either; -use ufotofu::local_nb::BulkProducer; +use syncify::syncify; -use crate::encoding::error::DecodeError; +#[syncify(encoding_sync)] +pub(super) mod encoding { -/// Have `Producer` produce a single byte, or return an error if the final value was produced or the producer experienced an error. -pub async fn produce_byte( - producer: &mut Producer, -) -> Result> -where - Producer: BulkProducer, -{ - match producer.produce().await { - Ok(Either::Left(item)) => Ok(item), - Ok(Either::Right(_)) => Err(DecodeError::InvalidInput), - Err(err) => Err(DecodeError::Producer(err)), + use crate::encoding::error::DecodeError; + + use either::Either; + use syncify::syncify_replace; + + #[syncify_replace(use ufotofu::sync::{ BulkProducer};)] + use ufotofu::local_nb::BulkProducer; + + /// Have `Producer` produce a single byte, or return an error if the final value was produced or the producer experienced an error. + pub async fn produce_byte( + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + { + match producer.produce().await { + Ok(Either::Left(item)) => Ok(item), + Ok(Either::Right(_)) => Err(DecodeError::InvalidInput), + Err(err) => Err(DecodeError::Producer(err)), + } } } diff --git a/data-model/src/encoding/compact_width.rs b/data-model/src/encoding/compact_width.rs index e988d48..fffc7f9 100644 --- a/data-model/src/encoding/compact_width.rs +++ b/data-model/src/encoding/compact_width.rs @@ -1,7 +1,4 @@ use crate::encoding::error::DecodeError; -use crate::encoding::parameters::Decodable; -use crate::encoding::unsigned_int::{U16BE, U32BE, U64BE, U8BE}; -use ufotofu::local_nb::{BulkConsumer, BulkProducer}; /// A minimum width of bytes needed to represent a unsigned integer. #[derive(PartialEq, Eq, Debug)] @@ -108,44 +105,61 @@ impl CompactWidth { } } -/// Encode a `u64` integer as a `compact_width(value)`-byte big-endian integer, and consume that with a [`BulkConsumer`]. -pub async fn encode_compact_width_be>( - value: u64, - consumer: &mut Consumer, -) -> Result<(), Consumer::Error> { - let width = CompactWidth::from_u64(value).width(); +use syncify::syncify; +use syncify::syncify_replace; - consumer - .bulk_consume_full_slice(&value.to_be_bytes()[8 - width..]) - .await - .map_err(|f| f.reason)?; +#[syncify(encoding_sync)] +pub(super) mod encoding { + use super::*; - Ok(()) -} + #[syncify_replace(use ufotofu::sync::{BulkConsumer, BulkProducer};)] + use ufotofu::local_nb::{BulkConsumer, BulkProducer}; + + use crate::encoding::unsigned_int::{U16BE, U32BE, U64BE, U8BE}; + + #[syncify_replace(use crate::encoding::parameters_sync::{Decodable, };)] + use crate::encoding::parameters::Decodable; + + /// Encode a `u64` integer as a `compact_width(value)`-byte big-endian integer, and consume that with a [`BulkConsumer`]. + pub async fn encode_compact_width_be>( + value: u64, + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> { + let width = CompactWidth::from_u64(value).width(); -/// Decode the bytes representing a [`compact-width`]-bytes integer into a `usize`. -pub async fn decode_compact_width_be>( - compact_width: CompactWidth, - producer: &mut Producer, -) -> Result> { - let decoded = match compact_width { - CompactWidth::One => U8BE::decode(producer).await.map(u64::from), - CompactWidth::Two => U16BE::decode(producer).await.map(u64::from), - CompactWidth::Four => U32BE::decode(producer).await.map(u64::from), - CompactWidth::Eight => U64BE::decode(producer).await.map(u64::from), - }?; - - let real_width = CompactWidth::from_u64(decoded); - - if real_width != compact_width { - return Err(DecodeError::InvalidInput); + consumer + .bulk_consume_full_slice(&value.to_be_bytes()[8 - width..]) + .await + .map_err(|f| f.reason)?; + + Ok(()) } - Ok(decoded) + /// Decode the bytes representing a [`compact-width`]-bytes integer into a `usize`. + pub async fn decode_compact_width_be>( + compact_width: CompactWidth, + producer: &mut Producer, + ) -> Result> { + let decoded = match compact_width { + CompactWidth::One => U8BE::decode(producer).await.map(u64::from), + CompactWidth::Two => U16BE::decode(producer).await.map(u64::from), + CompactWidth::Four => U32BE::decode(producer).await.map(u64::from), + CompactWidth::Eight => U64BE::decode(producer).await.map(u64::from), + }?; + + let real_width = CompactWidth::from_u64(decoded); + + if real_width != compact_width { + return Err(DecodeError::InvalidInput); + } + + Ok(decoded) + } } #[cfg(test)] mod tests { + use encoding_sync::{decode_compact_width_be, encode_compact_width_be}; use ufotofu::local_nb::consumer::IntoVec; use ufotofu::local_nb::producer::FromBoxedSlice; @@ -219,26 +233,23 @@ mod tests { (CompactWidth::Eight, u64::MAX), ]; - smol::block_on(async { - for (compact_width, value) in values { - let mut consumer = IntoVec::::new(); + for (compact_width, value) in values { + let mut consumer = IntoVec::::new(); - encode_compact_width_be(value, &mut consumer).await.unwrap(); + encode_compact_width_be(value, &mut consumer).unwrap(); - let encode_result = consumer.into_vec(); + let encode_result = consumer.into_vec(); - let decoded_compact_width = CompactWidth::new(encode_result.len() as u8).unwrap(); + let decoded_compact_width = CompactWidth::new(encode_result.len() as u8).unwrap(); - assert_eq!(decoded_compact_width, compact_width); + assert_eq!(decoded_compact_width, compact_width); - let mut producer = FromBoxedSlice::from_vec(encode_result); + let mut producer = FromBoxedSlice::from_vec(encode_result); - let decode_result = decode_compact_width_be(decoded_compact_width, &mut producer) - .await - .unwrap(); + let decode_result = + decode_compact_width_be(decoded_compact_width, &mut producer).unwrap(); - assert_eq!(decode_result, value); - } - }); + assert_eq!(decode_result, value); + } } } diff --git a/data-model/src/encoding/parameters.rs b/data-model/src/encoding/parameters.rs index cf3d458..7b47bbf 100644 --- a/data-model/src/encoding/parameters.rs +++ b/data-model/src/encoding/parameters.rs @@ -32,3 +32,29 @@ pub trait Decodable { Producer: BulkProducer, Self: Sized; } + +/// A type that can be used to encode `T` to a bytestring *encoded relative to `R`*. +/// This can be used to create more compact encodings from which `T` can be derived by anyone with `R`. +pub trait RelativeEncodable { + /// A function from the set `Self` to the set of bytestrings *encoded relative to `reference`*. + fn relative_encode( + &self, + reference: &R, + consumer: &mut Consumer, + ) -> impl Future> + where + Consumer: BulkConsumer; +} + +/// A type that can be used to decode `T` from a bytestring *encoded relative to `Self`*. +/// This can be used to decode a compact encoding frow which `T` can be derived by anyone with `R`. +pub trait RelativeDecodable { + /// A function from the set of bytestrings *encoded relative to `Self`* to the set of `T` in relation to `Self`. + fn relative_decode( + reference: &R, + producer: &mut Producer, + ) -> impl Future>> + where + Producer: BulkProducer, + Self: Sized; +} diff --git a/data-model/src/encoding/parameters_sync.rs b/data-model/src/encoding/parameters_sync.rs index 0764283..cfd15a1 100644 --- a/data-model/src/encoding/parameters_sync.rs +++ b/data-model/src/encoding/parameters_sync.rs @@ -1,5 +1,3 @@ -use std::future::Future; - use crate::encoding::error::DecodeError; use ufotofu::sync::{BulkConsumer, BulkProducer}; @@ -10,10 +8,7 @@ pub trait Encodable { /// A function from the set `Self` to the set of bytestrings. /// /// [Definition](https://willowprotocol.org/specs/encodings/index.html#encode_s) - fn encode( - &self, - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> + fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> where Consumer: BulkConsumer; } @@ -25,7 +20,31 @@ pub trait Decodable { /// A function from the set of bytestrings to the set of `T`. /// /// [Definition](https://willowprotocol.org/specs/encodings/index.html#decode_s) - fn decode( + fn decode(producer: &mut Producer) -> Result> + where + Producer: BulkProducer, + Self: Sized; +} + +/// A type that can be used to encode `T` to a bytestring *encoded relative to `R`*. +/// This can be used to create more compact encodings from which `T` can be derived by anyone with `R`. +pub trait RelativeEncodable { + /// A function from the set `Self` to the set of bytestrings *encoded relative to `reference`*. + fn relative_encode( + &self, + reference: &R, + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer; +} + +/// A type that can be used to decode `T` from a bytestring *encoded relative to `Self`*. +/// This can be used to decode a compact encoding frow which `T` can be derived by anyone with `R`. +pub trait RelativeDecodable { + /// A function from the set of bytestrings *encoded relative to `Self`* to the set of `T` in relation to `Self`. + fn relative_decode( + reference: &R, producer: &mut Producer, ) -> Result> where diff --git a/data-model/src/encoding/relativity.rs b/data-model/src/encoding/relativity.rs index d814dd3..7d8fd28 100644 --- a/data-model/src/encoding/relativity.rs +++ b/data-model/src/encoding/relativity.rs @@ -1,107 +1,169 @@ -use core::future::Future; -use core::mem::{size_of, MaybeUninit}; -use ufotofu::local_nb::{BulkConsumer, BulkProducer}; - -use crate::{ - encoding::{ - bytes::{is_bitflagged, produce_byte}, - compact_width::{decode_compact_width_be, encode_compact_width_be, CompactWidth}, - error::DecodeError, - max_power::{decode_max_power, encode_max_power}, - parameters::{Decodable, Encodable}, - }, - entry::Entry, - grouping::{ - area::{Area, AreaSubspace}, - range::{Range, RangeEnd}, - range_3d::Range3d, - }, - parameters::{NamespaceId, PayloadDigest, SubspaceId}, - path::Path, -}; - -use super::shared_buffers::ScratchSpacePathDecoding; - -/// A type that can be used to encode `T` to a bytestring *encoded relative to `R`*. -/// This can be used to create more compact encodings from which `T` can be derived by anyone with `R`. -pub trait RelativeEncodable { - /// A function from the set `Self` to the set of bytestrings *encoded relative to `reference`*. - fn relative_encode( - &self, - reference: &R, - consumer: &mut Consumer, - ) -> impl Future> - where - Consumer: BulkConsumer; -} - -/// A type that can be used to decode `T` from a bytestring *encoded relative to `Self`*. -/// This can be used to decode a compact encoding frow which `T` can be derived by anyone with `R`. -pub trait RelativeDecodable { - /// A function from the set of bytestrings *encoded relative to `Self`* to the set of `T` in relation to `Self`. - fn relative_decode( - reference: &R, - producer: &mut Producer, - ) -> impl Future>> - where - Producer: BulkProducer, - Self: Sized; -} - -// Path <> Path - -impl RelativeEncodable> - for Path -{ - /// Encode a path relative to another path. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_path_relative) - async fn relative_encode( - &self, - reference: &Path, - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> - where - Consumer: BulkConsumer, +use syncify::syncify; +use syncify::syncify_replace; + +#[syncify(encoding_sync)] +pub(super) mod encoding { + use super::*; + + #[syncify_replace(use ufotofu::sync::{BulkConsumer, BulkProducer};)] + use ufotofu::local_nb::{BulkConsumer, BulkProducer}; + + #[syncify_replace(use crate::encoding::parameters_sync::{Encodable, Decodable, RelativeDecodable, RelativeEncodable};)] + use crate::encoding::parameters::{Decodable, Encodable, RelativeDecodable, RelativeEncodable}; + + #[syncify_replace(use crate::encoding::max_power_sync::{decode_max_power, encode_max_power};)] + use crate::encoding::max_power::{decode_max_power, encode_max_power}; + + #[syncify_replace(use crate::encoding::compact_width::encoding_sync::{ decode_compact_width_be, encode_compact_width_be};)] + use crate::encoding::compact_width::encoding::{ + decode_compact_width_be, encode_compact_width_be, + }; + + #[syncify_replace(use crate::encoding::bytes::encoding_sync::produce_byte;)] + use crate::encoding::bytes::encoding::produce_byte; + + use core::mem::{size_of, MaybeUninit}; + + use crate::{ + encoding::{ + bytes::is_bitflagged, compact_width::CompactWidth, error::DecodeError, + shared_buffers::ScratchSpacePathDecoding, + }, + entry::Entry, + grouping::{ + area::{Area, AreaSubspace}, + range::{Range, RangeEnd}, + range_3d::Range3d, + }, + parameters::{NamespaceId, PayloadDigest, SubspaceId}, + path::Path, + }; + + // Path <> Path + impl + RelativeEncodable> for Path { - let lcp = self.longest_common_prefix(reference); - let lcp_component_count = lcp.get_component_count(); - encode_max_power(lcp_component_count, MCC, consumer).await?; + /// Encode a path relative to another path. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_path_relative) + async fn relative_encode( + &self, + reference: &Path, + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let lcp = self.longest_common_prefix(reference); + let lcp_component_count = lcp.get_component_count(); + encode_max_power(lcp_component_count, MCC, consumer).await?; - let suffix_component_count = self.get_component_count() - lcp_component_count; - encode_max_power(suffix_component_count, MCC, consumer).await?; + let suffix_component_count = self.get_component_count() - lcp_component_count; + encode_max_power(suffix_component_count, MCC, consumer).await?; - for component in self.suffix_components(lcp_component_count) { - encode_max_power(component.len(), MCL, consumer).await?; + for component in self.suffix_components(lcp_component_count) { + encode_max_power(component.len(), MCL, consumer).await?; - consumer - .bulk_consume_full_slice(component.as_ref()) - .await - .map_err(|f| f.reason)?; - } + consumer + .bulk_consume_full_slice(component.as_ref()) + .await + .map_err(|f| f.reason)?; + } - Ok(()) + Ok(()) + } } -} -impl RelativeDecodable> - for Path -{ - /// Decode a path relative to this path. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_path_relative) - async fn relative_decode( - reference: &Path, - producer: &mut Producer, - ) -> Result> - where - Producer: BulkProducer, - Self: Sized, + impl + RelativeDecodable> for Path { - let lcp_component_count: usize = decode_max_power(MCC, producer).await?.try_into()?; + /// Decode a path relative to this path. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_path_relative) + async fn relative_decode( + reference: &Path, + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let lcp_component_count: usize = decode_max_power(MCC, producer).await?.try_into()?; + + if lcp_component_count == 0 { + let decoded = Path::::decode(producer).await?; + + // === Necessary to produce canonic encodings. === + if lcp_component_count + != decoded + .longest_common_prefix(reference) + .get_component_count() + { + return Err(DecodeError::InvalidInput); + } + // =============================================== + + return Ok(decoded); + } + + let prefix = reference + .create_prefix(lcp_component_count as usize) + .ok_or(DecodeError::InvalidInput)?; + + let mut buf = ScratchSpacePathDecoding::::new(); - if lcp_component_count == 0 { - let decoded = Path::::decode(producer).await?; + // Copy the accumulated component lengths of the prefix into the scratch buffer. + let raw_prefix_acc_component_lengths = &prefix.raw_buf() + [size_of::()..size_of::() * (lcp_component_count + 1)]; + unsafe { + // Safe because len is less than size_of::() times the MCC, because `prefix` respects the MCC. + buf.set_many_component_accumulated_lengths_from_ne( + raw_prefix_acc_component_lengths, + ); + } + + // Copy the raw path data of the prefix into the scratch buffer. + unsafe { + // safe because we just copied the accumulated component lengths for the first `lcp_component_count` components. + MaybeUninit::copy_from_slice( + buf.path_data_until_as_mut(lcp_component_count), + &reference.raw_buf()[size_of::() * (reference.get_component_count() + 1) + ..size_of::() * (reference.get_component_count() + 1) + + prefix.get_path_length()], + ); + } + + let remaining_component_count: usize = + decode_max_power(MCC, producer).await?.try_into()?; + let total_component_count = lcp_component_count + remaining_component_count; + if total_component_count > MCC { + return Err(DecodeError::InvalidInput); + } + + let mut accumulated_component_length: usize = prefix.get_path_length(); // Always holds the acc length of all components we copied so far. + for i in lcp_component_count..total_component_count { + let component_len: usize = decode_max_power(MCL, producer).await?.try_into()?; + if component_len > MCL { + return Err(DecodeError::InvalidInput); + } + + accumulated_component_length += component_len; + if accumulated_component_length > MPL { + return Err(DecodeError::InvalidInput); + } + + buf.set_component_accumulated_length(accumulated_component_length, i); + + // Decode the component itself into the scratch buffer. + producer + .bulk_overwrite_full_slice_uninit(unsafe { + // Safe because we called set_component_Accumulated_length for all j <= i + buf.path_data_as_mut(i) + }) + .await?; + } + + let decoded = unsafe { buf.to_path(total_component_count) }; // === Necessary to produce canonic encodings. === if lcp_component_count @@ -113,1217 +175,1157 @@ impl RelativeDecodable::new(); + // Entry <> Entry - // Copy the accumulated component lengths of the prefix into the scratch buffer. - let raw_prefix_acc_component_lengths = - &prefix.raw_buf()[size_of::()..size_of::() * (lcp_component_count + 1)]; - unsafe { - // Safe because len is less than size_of::() times the MCC, because `prefix` respects the MCC. - buf.set_many_component_accumulated_lengths_from_ne(raw_prefix_acc_component_lengths); - } + impl + RelativeEncodable> for Entry + where + N: NamespaceId + Encodable, + S: SubspaceId + Encodable, + PD: PayloadDigest + Encodable, + { + /// Encode an [`Entry`] relative to a reference [`Entry`]. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_etry_relative_entry). + async fn relative_encode( + &self, + reference: &Entry, + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let time_diff = self.timestamp().abs_diff(reference.timestamp()); - // Copy the raw path data of the prefix into the scratch buffer. - unsafe { - // safe because we just copied the accumulated component lengths for the first `lcp_component_count` components. - MaybeUninit::copy_from_slice( - buf.path_data_until_as_mut(lcp_component_count), - &reference.raw_buf()[size_of::() * (reference.get_component_count() + 1) - ..size_of::() * (reference.get_component_count() + 1) - + prefix.get_path_length()], - ); - } + let mut header: u8 = 0b0000_0000; - let remaining_component_count: usize = decode_max_power(MCC, producer).await?.try_into()?; - let total_component_count = lcp_component_count + remaining_component_count; - if total_component_count > MCC { - return Err(DecodeError::InvalidInput); - } + if self.namespace_id() != reference.namespace_id() { + header |= 0b1000_0000; + } - let mut accumulated_component_length: usize = prefix.get_path_length(); // Always holds the acc length of all components we copied so far. - for i in lcp_component_count..total_component_count { - let component_len: usize = decode_max_power(MCL, producer).await?.try_into()?; - if component_len > MCL { - return Err(DecodeError::InvalidInput); + if self.subspace_id() != reference.subspace_id() { + header |= 0b0100_0000; } - accumulated_component_length += component_len; - if accumulated_component_length > MPL { - return Err(DecodeError::InvalidInput); + if self.timestamp() > reference.timestamp() { + header |= 0b0010_0000; } - buf.set_component_accumulated_length(accumulated_component_length, i); + header |= CompactWidth::from_u64(time_diff).bitmask(4); - // Decode the component itself into the scratch buffer. - producer - .bulk_overwrite_full_slice_uninit(unsafe { - // Safe because we called set_component_Accumulated_length for all j <= i - buf.path_data_as_mut(i) - }) - .await?; - } + header |= CompactWidth::from_u64(self.payload_length()).bitmask(6); - let decoded = unsafe { buf.to_path(total_component_count) }; + consumer.consume(header).await?; - // === Necessary to produce canonic encodings. === - if lcp_component_count - != decoded - .longest_common_prefix(reference) - .get_component_count() - { - return Err(DecodeError::InvalidInput); - } - // =============================================== + if self.namespace_id() != reference.namespace_id() { + self.namespace_id().encode(consumer).await?; + } - Ok(decoded) - } -} + if self.subspace_id() != reference.subspace_id() { + self.subspace_id().encode(consumer).await?; + } -// Entry <> Entry - -impl - RelativeEncodable> for Entry -where - N: NamespaceId + Encodable, - S: SubspaceId + Encodable, - PD: PayloadDigest + Encodable, -{ - /// Encode an [`Entry`] relative to a reference [`Entry`]. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_etry_relative_entry). - async fn relative_encode( - &self, - reference: &Entry, - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> - where - Consumer: BulkConsumer, - { - let time_diff = self.timestamp().abs_diff(reference.timestamp()); + self.path() + .relative_encode(reference.path(), consumer) + .await?; - let mut header: u8 = 0b0000_0000; + encode_compact_width_be(time_diff, consumer).await?; - if self.namespace_id() != reference.namespace_id() { - header |= 0b1000_0000; - } + encode_compact_width_be(self.payload_length(), consumer).await?; - if self.subspace_id() != reference.subspace_id() { - header |= 0b0100_0000; - } + self.payload_digest().encode(consumer).await?; - if self.timestamp() > reference.timestamp() { - header |= 0b0010_0000; + Ok(()) } + } - header |= CompactWidth::from_u64(time_diff).bitmask(4); + impl + RelativeDecodable> for Entry + where + N: NamespaceId + Decodable + std::fmt::Debug, + S: SubspaceId + Decodable + std::fmt::Debug, + PD: PayloadDigest + Decodable, + { + /// Decode an [`Entry`] relative from this [`Entry`]. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_etry_relative_entry). + async fn relative_decode( + reference: &Entry, + producer: &mut Producer, + ) -> Result, DecodeError> + where + Producer: BulkProducer, + Self: Sized, + { + let header = produce_byte(producer).await?; - header |= CompactWidth::from_u64(self.payload_length()).bitmask(6); + // Verify that bit 3 is 0 as specified. + if is_bitflagged(header, 3) { + return Err(DecodeError::InvalidInput); + } - consumer.consume(header).await?; + let is_namespace_encoded = is_bitflagged(header, 0); + let is_subspace_encoded = is_bitflagged(header, 1); + let add_or_subtract_time_diff = is_bitflagged(header, 2); + let compact_width_time_diff = CompactWidth::decode_fixed_width_bitmask(header, 4); + let compact_width_payload_length = CompactWidth::decode_fixed_width_bitmask(header, 6); - if self.namespace_id() != reference.namespace_id() { - self.namespace_id().encode(consumer).await?; - } + let namespace_id = if is_namespace_encoded { + N::decode(producer).await? + } else { + reference.namespace_id().clone() + }; - if self.subspace_id() != reference.subspace_id() { - self.subspace_id().encode(consumer).await?; - } + /* + // Verify that the encoded namespace wasn't the same as ours + // Which would indicate invalid input + if is_namespace_encoded && namespace_id == reference.get_namespace_id() { + return Err(DecodeError::InvalidInput); + } + */ - self.path() - .relative_encode(reference.path(), consumer) - .await?; + let subspace_id = if is_subspace_encoded { + S::decode(producer).await? + } else { + reference.subspace_id().clone() + }; - encode_compact_width_be(time_diff, consumer).await?; + /* + // Verify that the encoded subspace wasn't the same as ours + // Which would indicate invalid input + if is_subspace_encoded && subspace_id == reference.get_subspace_id() { + return Err(DecodeError::InvalidInput); + } + */ - encode_compact_width_be(self.payload_length(), consumer).await?; + let path = Path::::relative_decode(reference.path(), producer).await?; - self.payload_digest().encode(consumer).await?; + let time_diff = decode_compact_width_be(compact_width_time_diff, producer).await?; - Ok(()) - } -} + // Add or subtract safely here to avoid overflows caused by malicious or faulty encodings. + let timestamp = if add_or_subtract_time_diff { + reference + .timestamp() + .checked_add(time_diff) + .ok_or(DecodeError::InvalidInput)? + } else { + reference + .timestamp() + .checked_sub(time_diff) + .ok_or(DecodeError::InvalidInput)? + }; + + /* + // Verify that the correct add_or_subtract_time_diff flag was set. + let should_have_subtracted = timestamp <= reference.get_timestamp(); + if add_or_subtract_time_diff && should_have_subtracted { + return Err(DecodeError::InvalidInput); + } + */ -impl - RelativeDecodable> for Entry -where - N: NamespaceId + Decodable + std::fmt::Debug, - S: SubspaceId + Decodable + std::fmt::Debug, - PD: PayloadDigest + Decodable, -{ - /// Decode an [`Entry`] relative from this [`Entry`]. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_etry_relative_entry). - async fn relative_decode( - reference: &Entry, - producer: &mut Producer, - ) -> Result, DecodeError> - where - Producer: BulkProducer, - Self: Sized, - { - let header = produce_byte(producer).await?; + let payload_length = + decode_compact_width_be(compact_width_payload_length, producer).await?; - // Verify that bit 3 is 0 as specified. - if is_bitflagged(header, 3) { - return Err(DecodeError::InvalidInput); - } + let payload_digest = PD::decode(producer).await?; - let is_namespace_encoded = is_bitflagged(header, 0); - let is_subspace_encoded = is_bitflagged(header, 1); - let add_or_subtract_time_diff = is_bitflagged(header, 2); - let compact_width_time_diff = CompactWidth::decode_fixed_width_bitmask(header, 4); - let compact_width_payload_length = CompactWidth::decode_fixed_width_bitmask(header, 6); - - let namespace_id = if is_namespace_encoded { - N::decode(producer).await? - } else { - reference.namespace_id().clone() - }; - - /* - // Verify that the encoded namespace wasn't the same as ours - // Which would indicate invalid input - if is_namespace_encoded && namespace_id == reference.get_namespace_id() { - return Err(DecodeError::InvalidInput); - } - */ - - let subspace_id = if is_subspace_encoded { - S::decode(producer).await? - } else { - reference.subspace_id().clone() - }; - - /* - // Verify that the encoded subspace wasn't the same as ours - // Which would indicate invalid input - if is_subspace_encoded && subspace_id == reference.get_subspace_id() { - return Err(DecodeError::InvalidInput); - } - */ - - let path = Path::::relative_decode(reference.path(), producer).await?; - - let time_diff = decode_compact_width_be(compact_width_time_diff, producer).await?; - - // Add or subtract safely here to avoid overflows caused by malicious or faulty encodings. - let timestamp = if add_or_subtract_time_diff { - reference - .timestamp() - .checked_add(time_diff) - .ok_or(DecodeError::InvalidInput)? - } else { - reference - .timestamp() - .checked_sub(time_diff) - .ok_or(DecodeError::InvalidInput)? - }; - - /* - // Verify that the correct add_or_subtract_time_diff flag was set. - let should_have_subtracted = timestamp <= reference.get_timestamp(); - if add_or_subtract_time_diff && should_have_subtracted { - return Err(DecodeError::InvalidInput); + Ok(Entry::new( + namespace_id, + subspace_id, + path, + timestamp, + payload_length, + payload_digest, + )) } - */ - - let payload_length = - decode_compact_width_be(compact_width_payload_length, producer).await?; - - let payload_digest = PD::decode(producer).await?; - - Ok(Entry::new( - namespace_id, - subspace_id, - path, - timestamp, - payload_length, - payload_digest, - )) } -} -impl - RelativeEncodable<(N, Area)> for Entry -where - N: NamespaceId + Encodable, - S: SubspaceId + Encodable, - PD: PayloadDigest + Encodable, -{ - /// Encode an [`Entry`] relative to a reference [`NamespaceId`] and [`Area`]. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_area). - async fn relative_encode( - &self, - reference: &(N, Area), - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> + impl + RelativeEncodable<(N, Area)> for Entry where - Consumer: BulkConsumer, + N: NamespaceId + Encodable, + S: SubspaceId + Encodable, + PD: PayloadDigest + Encodable, { - let (namespace, out) = reference; + /// Encode an [`Entry`] relative to a reference [`NamespaceId`] and [`Area`]. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_area). + async fn relative_encode( + &self, + reference: &(N, Area), + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let (namespace, out) = reference; - if self.namespace_id() != namespace { - panic!("Tried to encode an entry relative to a namespace it does not belong to") - } + if self.namespace_id() != namespace { + panic!("Tried to encode an entry relative to a namespace it does not belong to") + } - if !out.includes_entry(self) { - panic!("Tried to encode an entry relative to an area it is not included by") - } + if !out.includes_entry(self) { + panic!("Tried to encode an entry relative to an area it is not included by") + } - let time_diff = core::cmp::min( - self.timestamp() - out.times().start, - u64::from(&out.times().end) - self.timestamp(), - ); + let time_diff = core::cmp::min( + self.timestamp() - out.times().start, + u64::from(&out.times().end) - self.timestamp(), + ); - let mut header = 0b0000_0000; + let mut header = 0b0000_0000; - if out.subspace().is_any() { - header |= 0b1000_0000; - } + if out.subspace().is_any() { + header |= 0b1000_0000; + } - if self.timestamp() - out.times().start <= u64::from(&out.times().end) - self.timestamp() { - header |= 0b0100_0000; - } + if self.timestamp() - out.times().start + <= u64::from(&out.times().end) - self.timestamp() + { + header |= 0b0100_0000; + } - header |= CompactWidth::from_u64(time_diff).bitmask(2); - header |= CompactWidth::from_u64(self.payload_length()).bitmask(4); + header |= CompactWidth::from_u64(time_diff).bitmask(2); + header |= CompactWidth::from_u64(self.payload_length()).bitmask(4); - consumer.consume(header).await?; + consumer.consume(header).await?; - if out.subspace().is_any() { - self.subspace_id().encode(consumer).await?; - } + if out.subspace().is_any() { + self.subspace_id().encode(consumer).await?; + } - self.path().relative_encode(out.path(), consumer).await?; - encode_compact_width_be(time_diff, consumer).await?; - encode_compact_width_be(self.payload_length(), consumer).await?; - self.payload_digest().encode(consumer).await?; + self.path().relative_encode(out.path(), consumer).await?; + encode_compact_width_be(time_diff, consumer).await?; + encode_compact_width_be(self.payload_length(), consumer).await?; + self.payload_digest().encode(consumer).await?; - Ok(()) + Ok(()) + } } -} -impl - RelativeDecodable<(N, Area)> for Entry -where - N: NamespaceId + Decodable, - S: SubspaceId + Decodable + std::fmt::Debug, - PD: PayloadDigest + Decodable, -{ - /// Decode an [`Entry`] relative to a reference [`NamespaceId`] and [`Area`]. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_area). - async fn relative_decode( - reference: &(N, Area), - producer: &mut Producer, - ) -> Result> + impl + RelativeDecodable<(N, Area)> for Entry where - Producer: BulkProducer, - Self: Sized, + N: NamespaceId + Decodable, + S: SubspaceId + Decodable + std::fmt::Debug, + PD: PayloadDigest + Decodable, { - let (namespace, out) = reference; - - let header = produce_byte(producer).await?; + /// Decode an [`Entry`] relative to a reference [`NamespaceId`] and [`Area`]. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_area). + async fn relative_decode( + reference: &(N, Area), + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let (namespace, out) = reference; - let is_subspace_encoded = is_bitflagged(header, 0); - let add_time_diff_to_start = is_bitflagged(header, 1); - let time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 2); - let payload_length_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 4); + let header = produce_byte(producer).await?; - if is_bitflagged(header, 6) || is_bitflagged(header, 7) { - return Err(DecodeError::InvalidInput); - } + let is_subspace_encoded = is_bitflagged(header, 0); + let add_time_diff_to_start = is_bitflagged(header, 1); + let time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 2); + let payload_length_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 4); - let subspace_id = if is_subspace_encoded { - match &out.subspace() { - AreaSubspace::Any => S::decode(producer).await?, - AreaSubspace::Id(_) => return Err(DecodeError::InvalidInput), - } - } else { - match &out.subspace() { - AreaSubspace::Any => return Err(DecodeError::InvalidInput), - AreaSubspace::Id(id) => id.clone(), + if is_bitflagged(header, 6) || is_bitflagged(header, 7) { + return Err(DecodeError::InvalidInput); } - }; - let path = Path::relative_decode(out.path(), producer).await?; + let subspace_id = if is_subspace_encoded { + match &out.subspace() { + AreaSubspace::Any => S::decode(producer).await?, + AreaSubspace::Id(_) => return Err(DecodeError::InvalidInput), + } + } else { + match &out.subspace() { + AreaSubspace::Any => return Err(DecodeError::InvalidInput), + AreaSubspace::Id(id) => id.clone(), + } + }; + + let path = Path::relative_decode(out.path(), producer).await?; - if !path.is_prefixed_by(out.path()) { - return Err(DecodeError::InvalidInput); - } + if !path.is_prefixed_by(out.path()) { + return Err(DecodeError::InvalidInput); + } - let time_diff = decode_compact_width_be(time_diff_compact_width, producer).await?; - let payload_length = - decode_compact_width_be(payload_length_compact_width, producer).await?; + let time_diff = decode_compact_width_be(time_diff_compact_width, producer).await?; + let payload_length = + decode_compact_width_be(payload_length_compact_width, producer).await?; - let payload_digest = PD::decode(producer).await?; + let payload_digest = PD::decode(producer).await?; - let timestamp = if add_time_diff_to_start { - out.times().start.checked_add(time_diff) - } else { - u64::from(&out.times().end).checked_sub(time_diff) - } - .ok_or(DecodeError::InvalidInput)?; + let timestamp = if add_time_diff_to_start { + out.times().start.checked_add(time_diff) + } else { + u64::from(&out.times().end).checked_sub(time_diff) + } + .ok_or(DecodeError::InvalidInput)?; - // === Necessary to produce canonic encodings. === - // Verify that the correct add_or_subtract_time_diff flag was set. - let should_have_added = timestamp.checked_sub(out.times().start) - <= u64::from(&out.times().end).checked_sub(timestamp); + // === Necessary to produce canonic encodings. === + // Verify that the correct add_or_subtract_time_diff flag was set. + let should_have_added = timestamp.checked_sub(out.times().start) + <= u64::from(&out.times().end).checked_sub(timestamp); - if add_time_diff_to_start != should_have_added { - return Err(DecodeError::InvalidInput); - } - // =============================================== + if add_time_diff_to_start != should_have_added { + return Err(DecodeError::InvalidInput); + } + // =============================================== - if !out.times().includes(×tamp) { - return Err(DecodeError::InvalidInput); - } + if !out.times().includes(×tamp) { + return Err(DecodeError::InvalidInput); + } - Ok(Self::new( - namespace.clone(), - subspace_id, - path, - timestamp, - payload_length, - payload_digest, - )) + Ok(Self::new( + namespace.clone(), + subspace_id, + path, + timestamp, + payload_length, + payload_digest, + )) + } } -} -impl - RelativeEncodable<(N, Range3d)> for Entry -where - N: NamespaceId + Encodable, - S: SubspaceId + Encodable, - PD: PayloadDigest + Encodable, -{ - /// Encode an [`Entry`] relative to a reference [`NamespaceId`] and [`Range3d`]. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_3drange). - async fn relative_encode( - &self, - reference: &(N, Range3d), - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> + impl + RelativeEncodable<(N, Range3d)> for Entry where - Consumer: BulkConsumer, + N: NamespaceId + Encodable, + S: SubspaceId + Encodable, + PD: PayloadDigest + Encodable, { - let (namespace, out) = reference; + /// Encode an [`Entry`] relative to a reference [`NamespaceId`] and [`Range3d`]. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_3drange). + async fn relative_encode( + &self, + reference: &(N, Range3d), + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let (namespace, out) = reference; - if self.namespace_id() != namespace { - panic!("Tried to encode an entry relative to a namespace it does not belong to") - } + if self.namespace_id() != namespace { + panic!("Tried to encode an entry relative to a namespace it does not belong to") + } - if !out.includes_entry(self) { - panic!("Tried to encode an entry relative to a 3d range it is not included by") - } + if !out.includes_entry(self) { + panic!("Tried to encode an entry relative to a 3d range it is not included by") + } - let time_diff = core::cmp::min( - self.timestamp().abs_diff(out.times().start), - self.timestamp().abs_diff(u64::from(&out.times().end)), - ); + let time_diff = core::cmp::min( + self.timestamp().abs_diff(out.times().start), + self.timestamp().abs_diff(u64::from(&out.times().end)), + ); - let mut header = 0b0000_0000; + let mut header = 0b0000_0000; - // Encode e.get_subspace_id()? - if self.subspace_id() != &out.subspaces().start { - header |= 0b1000_0000; - } + // Encode e.get_subspace_id()? + if self.subspace_id() != &out.subspaces().start { + header |= 0b1000_0000; + } - // Encode e.get_path() relative to out.get_paths().start or to out.get_paths().end? - let encode_path_relative_to_start = match &out.paths().end { - RangeEnd::Closed(end_path) => { - let start_lcp = self.path().longest_common_prefix(&out.paths().start); - let end_lcp = self.path().longest_common_prefix(end_path); + // Encode e.get_path() relative to out.get_paths().start or to out.get_paths().end? + let encode_path_relative_to_start = match &out.paths().end { + RangeEnd::Closed(end_path) => { + let start_lcp = self.path().longest_common_prefix(&out.paths().start); + let end_lcp = self.path().longest_common_prefix(end_path); - start_lcp.get_component_count() >= end_lcp.get_component_count() - } - RangeEnd::Open => true, - }; + start_lcp.get_component_count() >= end_lcp.get_component_count() + } + RangeEnd::Open => true, + }; - if encode_path_relative_to_start { - header |= 0b0100_0000; - } + if encode_path_relative_to_start { + header |= 0b0100_0000; + } - // Add time_diff to out.get_times().start, or subtract from out.get_times().end? - let add_time_diff_with_start = time_diff == self.timestamp().abs_diff(out.times().start); + // Add time_diff to out.get_times().start, or subtract from out.get_times().end? + let add_time_diff_with_start = + time_diff == self.timestamp().abs_diff(out.times().start); - if add_time_diff_with_start { - header |= 0b0010_0000; - } + if add_time_diff_with_start { + header |= 0b0010_0000; + } - // 2-bit integer n such that 2^n gives compact_width(time_diff) - header |= CompactWidth::from_u64(time_diff).bitmask(4); + // 2-bit integer n such that 2^n gives compact_width(time_diff) + header |= CompactWidth::from_u64(time_diff).bitmask(4); - // 2-bit integer n such that 2^n gives compact_width(e.get_payload_length()) - header |= CompactWidth::from_u64(self.payload_length()).bitmask(6); + // 2-bit integer n such that 2^n gives compact_width(e.get_payload_length()) + header |= CompactWidth::from_u64(self.payload_length()).bitmask(6); - consumer.consume(header).await?; + consumer.consume(header).await?; - if self.subspace_id() != &out.subspaces().start { - self.subspace_id().encode(consumer).await?; - } + if self.subspace_id() != &out.subspaces().start { + self.subspace_id().encode(consumer).await?; + } - // Encode e.get_path() relative to out.get_paths().start or to out.get_paths().end? - match &out.paths().end { - RangeEnd::Closed(end_path) => { - if encode_path_relative_to_start { + // Encode e.get_path() relative to out.get_paths().start or to out.get_paths().end? + match &out.paths().end { + RangeEnd::Closed(end_path) => { + if encode_path_relative_to_start { + self.path() + .relative_encode(&out.paths().start, consumer) + .await?; + } else { + self.path().relative_encode(end_path, consumer).await?; + } + } + RangeEnd::Open => { self.path() .relative_encode(&out.paths().start, consumer) .await?; - } else { - self.path().relative_encode(end_path, consumer).await?; } } - RangeEnd::Open => { - self.path() - .relative_encode(&out.paths().start, consumer) - .await?; - } - } - encode_compact_width_be(time_diff, consumer).await?; - encode_compact_width_be(self.payload_length(), consumer).await?; - self.payload_digest().encode(consumer).await?; + encode_compact_width_be(time_diff, consumer).await?; + encode_compact_width_be(self.payload_length(), consumer).await?; + self.payload_digest().encode(consumer).await?; - Ok(()) + Ok(()) + } } -} -impl - RelativeDecodable<(N, Range3d)> for Entry -where - N: NamespaceId + Decodable, - S: SubspaceId + Decodable + std::fmt::Debug, - PD: PayloadDigest + Decodable, -{ - /// Decode an [`Entry`] relative to a reference [`NamespaceId`] and [`Range3d`]. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_3drange). - async fn relative_decode( - reference: &(N, Range3d), - producer: &mut Producer, - ) -> Result> + impl + RelativeDecodable<(N, Range3d)> for Entry where - Producer: BulkProducer, - Self: Sized, + N: NamespaceId + Decodable, + S: SubspaceId + Decodable + std::fmt::Debug, + PD: PayloadDigest + Decodable, { - let (namespace, out) = reference; + /// Decode an [`Entry`] relative to a reference [`NamespaceId`] and [`Range3d`]. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_entry_in_namespace_3drange). + async fn relative_decode( + reference: &(N, Range3d), + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let (namespace, out) = reference; - let header = produce_byte(producer).await?; + let header = produce_byte(producer).await?; - // Decode e.get_subspace_id()? - let is_subspace_encoded = is_bitflagged(header, 0); + // Decode e.get_subspace_id()? + let is_subspace_encoded = is_bitflagged(header, 0); - // Decode e.get_path() relative to out.get_paths().start or to out.get_paths().end? - let decode_path_relative_to_start = is_bitflagged(header, 1); + // Decode e.get_path() relative to out.get_paths().start or to out.get_paths().end? + let decode_path_relative_to_start = is_bitflagged(header, 1); - // Add time_diff to out.get_times().start, or subtract from out.get_times().end? - let add_time_diff_with_start = is_bitflagged(header, 2); + // Add time_diff to out.get_times().start, or subtract from out.get_times().end? + let add_time_diff_with_start = is_bitflagged(header, 2); - if is_bitflagged(header, 3) { - return Err(DecodeError::InvalidInput); - } + if is_bitflagged(header, 3) { + return Err(DecodeError::InvalidInput); + } - let time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 4); - let payload_length_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 6); + let time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 4); + let payload_length_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 6); - let subspace_id = if is_subspace_encoded { - S::decode(producer).await? - } else { - out.subspaces().start.clone() - }; + let subspace_id = if is_subspace_encoded { + S::decode(producer).await? + } else { + out.subspaces().start.clone() + }; - // === Necessary to produce canonic encodings. === - // Verify that encoding the subspace was necessary. - if subspace_id == out.subspaces().start && is_subspace_encoded { - return Err(DecodeError::InvalidInput); - } - // =============================================== + // === Necessary to produce canonic encodings. === + // Verify that encoding the subspace was necessary. + if subspace_id == out.subspaces().start && is_subspace_encoded { + return Err(DecodeError::InvalidInput); + } + // =============================================== - // Verify that subspace is included by range - if !out.subspaces().includes(&subspace_id) { - return Err(DecodeError::InvalidInput); - } + // Verify that subspace is included by range + if !out.subspaces().includes(&subspace_id) { + return Err(DecodeError::InvalidInput); + } - let path = if decode_path_relative_to_start { - Path::relative_decode(&out.paths().start, producer).await? - } else { - match &out.paths().end { - RangeEnd::Closed(end_path) => Path::relative_decode(end_path, producer).await?, - RangeEnd::Open => return Err(DecodeError::InvalidInput), + let path = if decode_path_relative_to_start { + Path::relative_decode(&out.paths().start, producer).await? + } else { + match &out.paths().end { + RangeEnd::Closed(end_path) => Path::relative_decode(end_path, producer).await?, + RangeEnd::Open => return Err(DecodeError::InvalidInput), + } + }; + + // Verify that path is included by range + if !out.paths().includes(&path) { + return Err(DecodeError::InvalidInput); } - }; - // Verify that path is included by range - if !out.paths().includes(&path) { - return Err(DecodeError::InvalidInput); - } + // === Necessary to produce canonic encodings. === + // Verify that the path was encoded relative to the correct bound of the referenc path range. + let should_have_encoded_path_relative_to_start = match &out.paths().end { + RangeEnd::Closed(end_path) => { + let start_lcp = path.longest_common_prefix(&out.paths().start); + let end_lcp = path.longest_common_prefix(end_path); - // === Necessary to produce canonic encodings. === - // Verify that the path was encoded relative to the correct bound of the referenc path range. - let should_have_encoded_path_relative_to_start = match &out.paths().end { - RangeEnd::Closed(end_path) => { - let start_lcp = path.longest_common_prefix(&out.paths().start); - let end_lcp = path.longest_common_prefix(end_path); + start_lcp.get_component_count() >= end_lcp.get_component_count() + } + RangeEnd::Open => true, + }; - start_lcp.get_component_count() >= end_lcp.get_component_count() + if decode_path_relative_to_start != should_have_encoded_path_relative_to_start { + return Err(DecodeError::InvalidInput); } - RangeEnd::Open => true, - }; + // ================================================= - if decode_path_relative_to_start != should_have_encoded_path_relative_to_start { - return Err(DecodeError::InvalidInput); - } - // ================================================= + let time_diff = decode_compact_width_be(time_diff_compact_width, producer).await?; - let time_diff = decode_compact_width_be(time_diff_compact_width, producer).await?; + let payload_length = + decode_compact_width_be(payload_length_compact_width, producer).await?; - let payload_length = - decode_compact_width_be(payload_length_compact_width, producer).await?; + let payload_digest = PD::decode(producer).await?; - let payload_digest = PD::decode(producer).await?; + let timestamp = if add_time_diff_with_start { + out.times().start.checked_add(time_diff) + } else { + match &out.times().end { + RangeEnd::Closed(end_time) => end_time.checked_sub(time_diff), + RangeEnd::Open => u64::from(&out.times().end).checked_sub(time_diff), + } + } + .ok_or(DecodeError::InvalidInput)?; - let timestamp = if add_time_diff_with_start { - out.times().start.checked_add(time_diff) - } else { - match &out.times().end { - RangeEnd::Closed(end_time) => end_time.checked_sub(time_diff), - RangeEnd::Open => u64::from(&out.times().end).checked_sub(time_diff), + // Verify that timestamp is included by range + if !out.times().includes(×tamp) { + return Err(DecodeError::InvalidInput); } - } - .ok_or(DecodeError::InvalidInput)?; - // Verify that timestamp is included by range - if !out.times().includes(×tamp) { - return Err(DecodeError::InvalidInput); - } + // === Necessary to produce canonic encodings. === + // Verify that time_diff is what it should have been + let correct_time_diff = core::cmp::min( + timestamp.abs_diff(out.times().start), + timestamp.abs_diff(u64::from(&out.times().end)), + ); - // === Necessary to produce canonic encodings. === - // Verify that time_diff is what it should have been - let correct_time_diff = core::cmp::min( - timestamp.abs_diff(out.times().start), - timestamp.abs_diff(u64::from(&out.times().end)), - ); + if time_diff != correct_time_diff { + return Err(DecodeError::InvalidInput); + } - if time_diff != correct_time_diff { - return Err(DecodeError::InvalidInput); - } + // Verify that the combine with start bitflag in the header was correct + let should_have_added_to_start = time_diff == timestamp.abs_diff(out.times().start); - // Verify that the combine with start bitflag in the header was correct - let should_have_added_to_start = time_diff == timestamp.abs_diff(out.times().start); + if should_have_added_to_start != add_time_diff_with_start { + return Err(DecodeError::InvalidInput); + } + // ============================================== - if should_have_added_to_start != add_time_diff_with_start { - return Err(DecodeError::InvalidInput); + Ok(Self::new( + namespace.clone(), + subspace_id, + path, + timestamp, + payload_length, + payload_digest, + )) } - // ============================================== - - Ok(Self::new( - namespace.clone(), - subspace_id, - path, - timestamp, - payload_length, - payload_digest, - )) } -} -impl - RelativeEncodable> for Area -where - S: SubspaceId + Encodable, -{ - /// Encode an [`Area`] relative to another [`Area`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). - async fn relative_encode( - &self, - out: &Area, - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> + impl + RelativeEncodable> for Area where - Consumer: BulkConsumer, + S: SubspaceId + Encodable, { - if !out.includes_area(self) { - panic!("Tried to encode an area relative to a area it is not included by") - } + /// Encode an [`Area`] relative to another [`Area`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). + async fn relative_encode( + &self, + out: &Area, + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + if !out.includes_area(self) { + panic!("Tried to encode an area relative to a area it is not included by") + } - let start_diff = core::cmp::min( - self.times().start - out.times().start, - u64::from(&out.times().end) - self.times().start, - ); + let start_diff = core::cmp::min( + self.times().start - out.times().start, + u64::from(&out.times().end) - self.times().start, + ); - let end_diff = core::cmp::min( - u64::from(&self.times().end) - out.times().start, - u64::from(&out.times().end) - u64::from(&self.times().end), - ); + let end_diff = core::cmp::min( + u64::from(&self.times().end) - out.times().start, + u64::from(&out.times().end) - u64::from(&self.times().end), + ); - let mut header = 0; + let mut header = 0; - if self.subspace() != out.subspace() { - header |= 0b1000_0000; - } + if self.subspace() != out.subspace() { + header |= 0b1000_0000; + } - if self.times().end == RangeEnd::Open { - header |= 0b0100_0000; - } + if self.times().end == RangeEnd::Open { + header |= 0b0100_0000; + } - if start_diff == self.times().start - out.times().start { - header |= 0b0010_0000; - } + if start_diff == self.times().start - out.times().start { + header |= 0b0010_0000; + } - if self.times().end != RangeEnd::Open - && end_diff == u64::from(&self.times().end) - out.times().start - { - header |= 0b0001_0000; - } + if self.times().end != RangeEnd::Open + && end_diff == u64::from(&self.times().end) - out.times().start + { + header |= 0b0001_0000; + } - header |= CompactWidth::from_u64(start_diff).bitmask(4); - header |= CompactWidth::from_u64(end_diff).bitmask(6); + header |= CompactWidth::from_u64(start_diff).bitmask(4); + header |= CompactWidth::from_u64(end_diff).bitmask(6); - consumer.consume(header).await?; + consumer.consume(header).await?; - match (&self.subspace(), &out.subspace()) { - (AreaSubspace::Any, AreaSubspace::Any) => {} // Same subspace - (AreaSubspace::Id(_), AreaSubspace::Id(_)) => {} // Same subspace - (AreaSubspace::Id(subspace), AreaSubspace::Any) => { - subspace.encode(consumer).await?; - } - (AreaSubspace::Any, AreaSubspace::Id(_)) => { - unreachable!( - "We should have already rejected an area not included by another area!" - ) + match (&self.subspace(), &out.subspace()) { + (AreaSubspace::Any, AreaSubspace::Any) => {} // Same subspace + (AreaSubspace::Id(_), AreaSubspace::Id(_)) => {} // Same subspace + (AreaSubspace::Id(subspace), AreaSubspace::Any) => { + subspace.encode(consumer).await?; + } + (AreaSubspace::Any, AreaSubspace::Id(_)) => { + unreachable!( + "We should have already rejected an area not included by another area!" + ) + } } - } - self.path().relative_encode(out.path(), consumer).await?; + self.path().relative_encode(out.path(), consumer).await?; - encode_compact_width_be(start_diff, consumer).await?; + encode_compact_width_be(start_diff, consumer).await?; - if self.times().end != RangeEnd::Open { - encode_compact_width_be(end_diff, consumer).await?; - } + if self.times().end != RangeEnd::Open { + encode_compact_width_be(end_diff, consumer).await?; + } - Ok(()) + Ok(()) + } } -} -impl - RelativeDecodable> for Area -where - S: SubspaceId + Decodable, -{ - /// Decode an [`Area`] relative to another [`Area`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). - async fn relative_decode( - out: &Area, - producer: &mut Producer, - ) -> Result> + impl + RelativeDecodable> for Area where - Producer: BulkProducer, - Self: Sized, + S: SubspaceId + Decodable, { - let header = produce_byte(producer).await?; - - // Decode subspace? - let is_subspace_encoded = is_bitflagged(header, 0); - - // Decode end value of times? - let is_times_end_open = is_bitflagged(header, 1); - - // Add start_diff to out.get_times().start, or subtract from out.get_times().end? - let add_start_diff = is_bitflagged(header, 2); - - // Add end_diff to out.get_times().start, or subtract from out.get_times().end? - let add_end_diff = is_bitflagged(header, 3); + /// Decode an [`Area`] relative to another [`Area`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). + async fn relative_decode( + out: &Area, + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let header = produce_byte(producer).await?; - // === Necessary to produce canonic encodings. === - // Verify that we don't add_end_diff when open... - if add_end_diff && is_times_end_open { - return Err(DecodeError::InvalidInput); - } - // =============================================== + // Decode subspace? + let is_subspace_encoded = is_bitflagged(header, 0); - let start_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 4); - let end_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 6); + // Decode end value of times? + let is_times_end_open = is_bitflagged(header, 1); - // === Necessary to produce canonic encodings. === - // Verify the last two bits are zero if is_times_end_open - if is_times_end_open && (end_diff_compact_width != CompactWidth::One) { - return Err(DecodeError::InvalidInput); - } - // =============================================== + // Add start_diff to out.get_times().start, or subtract from out.get_times().end? + let add_start_diff = is_bitflagged(header, 2); - let subspace = if is_subspace_encoded { - let id = S::decode(producer).await?; - let sub = AreaSubspace::Id(id); + // Add end_diff to out.get_times().start, or subtract from out.get_times().end? + let add_end_diff = is_bitflagged(header, 3); // === Necessary to produce canonic encodings. === - // Verify that subspace wasn't needlessly encoded - if &sub == out.subspace() { + // Verify that we don't add_end_diff when open... + if add_end_diff && is_times_end_open { return Err(DecodeError::InvalidInput); } // =============================================== - sub - } else { - out.subspace().clone() - }; + let start_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 4); + let end_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header, 6); - // Verify that the decoded subspace is included by the reference subspace - match (&out.subspace(), &subspace) { - (AreaSubspace::Any, AreaSubspace::Any) => {} - (AreaSubspace::Any, AreaSubspace::Id(_)) => {} - (AreaSubspace::Id(_), AreaSubspace::Any) => { + // === Necessary to produce canonic encodings. === + // Verify the last two bits are zero if is_times_end_open + if is_times_end_open && (end_diff_compact_width != CompactWidth::One) { return Err(DecodeError::InvalidInput); } - (AreaSubspace::Id(a), AreaSubspace::Id(b)) => { - if a != b { - return Err(DecodeError::InvalidInput); - } - } - } - - let path = Path::relative_decode(out.path(), producer).await?; - - // Verify the decoded path is prefixed by the reference path - if !path.is_prefixed_by(out.path()) { - return Err(DecodeError::InvalidInput); - } - - let start_diff = decode_compact_width_be(start_diff_compact_width, producer).await?; - - let start = if add_start_diff { - out.times().start.checked_add(start_diff) - } else { - u64::from(&out.times().end).checked_sub(start_diff) - } - .ok_or(DecodeError::InvalidInput)?; + // =============================================== - // Verify they sent correct start diff - let expected_start_diff = core::cmp::min( - start.checked_sub(out.times().start), - u64::from(&out.times().end).checked_sub(start), - ) - .ok_or(DecodeError::InvalidInput)?; + let subspace = if is_subspace_encoded { + let id = S::decode(producer).await?; + let sub = AreaSubspace::Id(id); - if expected_start_diff != start_diff { - return Err(DecodeError::InvalidInput); - } + // === Necessary to produce canonic encodings. === + // Verify that subspace wasn't needlessly encoded + if &sub == out.subspace() { + return Err(DecodeError::InvalidInput); + } + // =============================================== - // === Necessary to produce canonic encodings. === - // Verify that bit 2 of the header was set correctly - let should_add_start_diff = start_diff - == start - .checked_sub(out.times().start) - .ok_or(DecodeError::InvalidInput)?; + sub + } else { + out.subspace().clone() + }; + + // Verify that the decoded subspace is included by the reference subspace + match (&out.subspace(), &subspace) { + (AreaSubspace::Any, AreaSubspace::Any) => {} + (AreaSubspace::Any, AreaSubspace::Id(_)) => {} + (AreaSubspace::Id(_), AreaSubspace::Any) => { + return Err(DecodeError::InvalidInput); + } + (AreaSubspace::Id(a), AreaSubspace::Id(b)) => { + if a != b { + return Err(DecodeError::InvalidInput); + } + } + } - if add_start_diff != should_add_start_diff { - return Err(DecodeError::InvalidInput); - } - // =============================================== + let path = Path::relative_decode(out.path(), producer).await?; - let end = if is_times_end_open { - if add_end_diff { + // Verify the decoded path is prefixed by the reference path + if !path.is_prefixed_by(out.path()) { return Err(DecodeError::InvalidInput); } - RangeEnd::Open - } else { - let end_diff = decode_compact_width_be(end_diff_compact_width, producer).await?; + let start_diff = decode_compact_width_be(start_diff_compact_width, producer).await?; - let end = if add_end_diff { - out.times().start.checked_add(end_diff) + let start = if add_start_diff { + out.times().start.checked_add(start_diff) } else { - u64::from(&out.times().end).checked_sub(end_diff) + u64::from(&out.times().end).checked_sub(start_diff) } .ok_or(DecodeError::InvalidInput)?; - // Verify they sent correct end diff - let expected_end_diff = core::cmp::min( - end.checked_sub(out.times().start), - u64::from(&out.times().end).checked_sub(end), + // Verify they sent correct start diff + let expected_start_diff = core::cmp::min( + start.checked_sub(out.times().start), + u64::from(&out.times().end).checked_sub(start), ) .ok_or(DecodeError::InvalidInput)?; - if end_diff != expected_end_diff { + if expected_start_diff != start_diff { return Err(DecodeError::InvalidInput); } // === Necessary to produce canonic encodings. === - let should_add_end_diff = end_diff - == end + // Verify that bit 2 of the header was set correctly + let should_add_start_diff = start_diff + == start .checked_sub(out.times().start) .ok_or(DecodeError::InvalidInput)?; - if add_end_diff != should_add_end_diff { + if add_start_diff != should_add_start_diff { return Err(DecodeError::InvalidInput); } - // ============================================ + // =============================================== + + let end = if is_times_end_open { + if add_end_diff { + return Err(DecodeError::InvalidInput); + } - RangeEnd::Closed(end) - }; + RangeEnd::Open + } else { + let end_diff = decode_compact_width_be(end_diff_compact_width, producer).await?; - let times = Range { start, end }; + let end = if add_end_diff { + out.times().start.checked_add(end_diff) + } else { + u64::from(&out.times().end).checked_sub(end_diff) + } + .ok_or(DecodeError::InvalidInput)?; - // Verify the decoded time range is included by the reference time range - if !out.times().includes_range(×) { - return Err(DecodeError::InvalidInput); - } + // Verify they sent correct end diff + let expected_end_diff = core::cmp::min( + end.checked_sub(out.times().start), + u64::from(&out.times().end).checked_sub(end), + ) + .ok_or(DecodeError::InvalidInput)?; + + if end_diff != expected_end_diff { + return Err(DecodeError::InvalidInput); + } + + // === Necessary to produce canonic encodings. === + let should_add_end_diff = end_diff + == end + .checked_sub(out.times().start) + .ok_or(DecodeError::InvalidInput)?; - Ok(Self::new(subspace, path, times)) + if add_end_diff != should_add_end_diff { + return Err(DecodeError::InvalidInput); + } + // ============================================ + + RangeEnd::Closed(end) + }; + + let times = Range { start, end }; + + // Verify the decoded time range is included by the reference time range + if !out.times().includes_range(×) { + return Err(DecodeError::InvalidInput); + } + + Ok(Self::new(subspace, path, times)) + } } -} -impl - RelativeEncodable> for Range3d -where - S: SubspaceId + Encodable + std::fmt::Debug, -{ - /// Encode an [`Range3d`] relative to another [`Range3d`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). - async fn relative_encode( - &self, - reference: &Range3d, - consumer: &mut Consumer, - ) -> Result<(), Consumer::Error> + impl + RelativeEncodable> for Range3d where - Consumer: BulkConsumer, + S: SubspaceId + Encodable + std::fmt::Debug, { - let start_to_start = self.times().start.abs_diff(reference.times().start); - let start_to_end = match reference.times().end { - RangeEnd::Closed(end) => self.times().start.abs_diff(end), - RangeEnd::Open => u64::MAX, - }; - let end_to_start = match self.times().end { - RangeEnd::Closed(end) => end.abs_diff(reference.times().start), - RangeEnd::Open => u64::MAX, - }; - let end_to_end = match (&self.times().end, &reference.times().end) { - (RangeEnd::Closed(self_end), RangeEnd::Closed(ref_end)) => self_end.abs_diff(*ref_end), - (RangeEnd::Closed(_), RangeEnd::Open) => u64::MAX, - (RangeEnd::Open, RangeEnd::Closed(_)) => u64::MAX, - (RangeEnd::Open, RangeEnd::Open) => 0, // shouldn't matter right??? - }; - - let start_time_diff = core::cmp::min(start_to_start, start_to_end); - - let end_time_diff = core::cmp::min(end_to_start, end_to_end); - - let mut header_1 = 0b0000_0000; - - // Bits 0, 1 - Encode r.get_subspaces().start? - if self.subspaces().start == reference.subspaces().start { - header_1 |= 0b0100_0000; - } else if reference.subspaces().end == self.subspaces().start { - header_1 |= 0b1000_0000; - } else { - header_1 |= 0b1100_0000; - } + /// Encode an [`Range3d`] relative to another [`Range3d`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). + async fn relative_encode( + &self, + reference: &Range3d, + consumer: &mut Consumer, + ) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let start_to_start = self.times().start.abs_diff(reference.times().start); + let start_to_end = match reference.times().end { + RangeEnd::Closed(end) => self.times().start.abs_diff(end), + RangeEnd::Open => u64::MAX, + }; + let end_to_start = match self.times().end { + RangeEnd::Closed(end) => end.abs_diff(reference.times().start), + RangeEnd::Open => u64::MAX, + }; + let end_to_end = match (&self.times().end, &reference.times().end) { + (RangeEnd::Closed(self_end), RangeEnd::Closed(ref_end)) => { + self_end.abs_diff(*ref_end) + } + (RangeEnd::Closed(_), RangeEnd::Open) => u64::MAX, + (RangeEnd::Open, RangeEnd::Closed(_)) => u64::MAX, + (RangeEnd::Open, RangeEnd::Open) => 0, // shouldn't matter right??? + }; - // Bits 2, 3 - Encode r.get_subspaces().end? - if self.subspaces().end == RangeEnd::Open { - // Do nothing - } else if self.subspaces().end == reference.subspaces().start { - header_1 |= 0b0001_0000; - } else if self.subspaces().end == reference.subspaces().end { - header_1 |= 0b0010_0000; - } else if self.subspaces().end != RangeEnd::Open { - header_1 |= 0b0011_0000; - } + let start_time_diff = core::cmp::min(start_to_start, start_to_end); - // Bit 4 - Encode r.get_paths().start relative to ref.get_paths().start or to ref.get_paths().end? - if let RangeEnd::Closed(ref_path_end) = &reference.paths().end { - let lcp_start_start = self - .paths() - .start - .longest_common_prefix(&reference.paths().start); - let lcp_start_end = self.paths().start.longest_common_prefix(ref_path_end); + let end_time_diff = core::cmp::min(end_to_start, end_to_end); - if lcp_start_start.get_component_count() >= lcp_start_end.get_component_count() { - header_1 |= 0b0000_1000; + let mut header_1 = 0b0000_0000; + + // Bits 0, 1 - Encode r.get_subspaces().start? + if self.subspaces().start == reference.subspaces().start { + header_1 |= 0b0100_0000; + } else if reference.subspaces().end == self.subspaces().start { + header_1 |= 0b1000_0000; + } else { + header_1 |= 0b1100_0000; } - } else { - header_1 |= 0b0000_1000; - } - // Bit 5 - Self path end open? - if self.paths().end == RangeEnd::Open { - header_1 |= 0b0000_0100; - } + // Bits 2, 3 - Encode r.get_subspaces().end? + if self.subspaces().end == RangeEnd::Open { + // Do nothing + } else if self.subspaces().end == reference.subspaces().start { + header_1 |= 0b0001_0000; + } else if self.subspaces().end == reference.subspaces().end { + header_1 |= 0b0010_0000; + } else if self.subspaces().end != RangeEnd::Open { + header_1 |= 0b0011_0000; + } - // Bit 6 - Encode r.get_paths().end relative to ref.get_paths().start or to ref.get_paths().end (if at all)? - match (&self.paths().end, &reference.paths().end) { - (RangeEnd::Closed(self_path_end), RangeEnd::Closed(ref_path_end)) => { - let lcp_end_start = self_path_end.longest_common_prefix(&reference.paths().start); - let lcp_end_end = self_path_end.longest_common_prefix(ref_path_end); + // Bit 4 - Encode r.get_paths().start relative to ref.get_paths().start or to ref.get_paths().end? + if let RangeEnd::Closed(ref_path_end) = &reference.paths().end { + let lcp_start_start = self + .paths() + .start + .longest_common_prefix(&reference.paths().start); + let lcp_start_end = self.paths().start.longest_common_prefix(ref_path_end); - if lcp_end_start.get_component_count() > lcp_end_end.get_component_count() { - header_1 |= 0b0000_0010; + if lcp_start_start.get_component_count() >= lcp_start_end.get_component_count() { + header_1 |= 0b0000_1000; } + } else { + header_1 |= 0b0000_1000; } - (RangeEnd::Closed(_), RangeEnd::Open) => { - header_1 |= 0b0000_0010; + + // Bit 5 - Self path end open? + if self.paths().end == RangeEnd::Open { + header_1 |= 0b0000_0100; } - (RangeEnd::Open, RangeEnd::Closed(_)) => {} - (RangeEnd::Open, RangeEnd::Open) => {} - } - // Bit 7 - Self time end open? - if self.times().end == RangeEnd::Open { - header_1 |= 0b0000_0001; - } + // Bit 6 - Encode r.get_paths().end relative to ref.get_paths().start or to ref.get_paths().end (if at all)? + match (&self.paths().end, &reference.paths().end) { + (RangeEnd::Closed(self_path_end), RangeEnd::Closed(ref_path_end)) => { + let lcp_end_start = + self_path_end.longest_common_prefix(&reference.paths().start); + let lcp_end_end = self_path_end.longest_common_prefix(ref_path_end); - consumer.consume(header_1).await?; + if lcp_end_start.get_component_count() > lcp_end_end.get_component_count() { + header_1 |= 0b0000_0010; + } + } + (RangeEnd::Closed(_), RangeEnd::Open) => { + header_1 |= 0b0000_0010; + } + (RangeEnd::Open, RangeEnd::Closed(_)) => {} + (RangeEnd::Open, RangeEnd::Open) => {} + } - let mut header_2 = 0b0000_0000; + // Bit 7 - Self time end open? + if self.times().end == RangeEnd::Open { + header_1 |= 0b0000_0001; + } - // Bit 8 - Encode r.get_times().start relative to ref.get_times().start or ref.get_times().end? - if start_to_start <= start_to_end { - header_2 |= 0b1000_0000; - } + consumer.consume(header_1).await?; - // Bit 9 -Add or subtract start_time_diff? - if is_bitflagged(header_2, 0) && self.times().start >= reference.times().start - || !is_bitflagged(header_2, 0) && self.times().start >= reference.times().end - { - header_2 |= 0b0100_0000; - } + let mut header_2 = 0b0000_0000; - // Bit 10, 11 - 2-bit integer n such that 2^n gives compact_width(start_time_diff) - header_2 |= CompactWidth::from_u64(start_time_diff).bitmask(2); + // Bit 8 - Encode r.get_times().start relative to ref.get_times().start or ref.get_times().end? + if start_to_start <= start_to_end { + header_2 |= 0b1000_0000; + } - // Bit 12 - Encode r.get_times().end relative to ref.get_times().start or ref.get_times().end (if at all)? - if self.times().end != RangeEnd::Open && end_to_start <= end_to_end { - header_2 |= 0b0000_1000; - } + // Bit 9 -Add or subtract start_time_diff? + if is_bitflagged(header_2, 0) && self.times().start >= reference.times().start + || !is_bitflagged(header_2, 0) && self.times().start >= reference.times().end + { + header_2 |= 0b0100_0000; + } - // Bit 13 - Add or subtract end_time_diff (if encoding it at all)? - if self.times().end == RangeEnd::Open { - // do nothing - } else if (is_bitflagged(header_2, 4) && self.times().end >= reference.times().start) - || (!is_bitflagged(header_2, 4) && self.times().end >= reference.times().end) - { - header_2 |= 0b0000_0100; - } + // Bit 10, 11 - 2-bit integer n such that 2^n gives compact_width(start_time_diff) + header_2 |= CompactWidth::from_u64(start_time_diff).bitmask(2); - // Bits 14, 15 - ignored, or 2-bit integer n such that 2^n gives compact_width(end_time_diff) - if self.times().end == RangeEnd::Open { - // do nothing - } else { - header_2 |= CompactWidth::from_u64(end_time_diff).bitmask(6); - } + // Bit 12 - Encode r.get_times().end relative to ref.get_times().start or ref.get_times().end (if at all)? + if self.times().end != RangeEnd::Open && end_to_start <= end_to_end { + header_2 |= 0b0000_1000; + } - consumer.consume(header_2).await?; + // Bit 13 - Add or subtract end_time_diff (if encoding it at all)? + if self.times().end == RangeEnd::Open { + // do nothing + } else if (is_bitflagged(header_2, 4) && self.times().end >= reference.times().start) + || (!is_bitflagged(header_2, 4) && self.times().end >= reference.times().end) + { + header_2 |= 0b0000_0100; + } - if (self.subspaces().start == reference.subspaces().start) - || (reference.subspaces().end == self.subspaces().start) - { - // Don't encode - } else { - self.subspaces().start.encode(consumer).await?; - } + // Bits 14, 15 - ignored, or 2-bit integer n such that 2^n gives compact_width(end_time_diff) + if self.times().end == RangeEnd::Open { + // do nothing + } else { + header_2 |= CompactWidth::from_u64(end_time_diff).bitmask(6); + } - if self.subspaces().end == RangeEnd::Open - || (self.subspaces().end == reference.subspaces().start) - || (self.subspaces().end == reference.subspaces().end) - { - // Don't encode end subspace - } else if let RangeEnd::Closed(end_subspace) = &self.subspaces().end { - end_subspace.encode(consumer).await?; - } + consumer.consume(header_2).await?; - if is_bitflagged(header_1, 4) { - self.paths() - .start - .relative_encode(&reference.paths().start, consumer) - .await?; - } else if let RangeEnd::Closed(end_path) = &reference.paths().end { - self.paths() - .start - .relative_encode(end_path, consumer) - .await?; - } + if (self.subspaces().start == reference.subspaces().start) + || (reference.subspaces().end == self.subspaces().start) + { + // Don't encode + } else { + self.subspaces().start.encode(consumer).await?; + } - if let RangeEnd::Closed(end_path) = &self.paths().end { - if is_bitflagged(header_1, 6) { - end_path + if self.subspaces().end == RangeEnd::Open + || (self.subspaces().end == reference.subspaces().start) + || (self.subspaces().end == reference.subspaces().end) + { + // Don't encode end subspace + } else if let RangeEnd::Closed(end_subspace) = &self.subspaces().end { + end_subspace.encode(consumer).await?; + } + + if is_bitflagged(header_1, 4) { + self.paths() + .start .relative_encode(&reference.paths().start, consumer) - .await? - } else if let RangeEnd::Closed(ref_end_path) = &reference.paths().end { - end_path.relative_encode(ref_end_path, consumer).await?; + .await?; + } else if let RangeEnd::Closed(end_path) = &reference.paths().end { + self.paths() + .start + .relative_encode(end_path, consumer) + .await?; + } + + if let RangeEnd::Closed(end_path) = &self.paths().end { + if is_bitflagged(header_1, 6) { + end_path + .relative_encode(&reference.paths().start, consumer) + .await? + } else if let RangeEnd::Closed(ref_end_path) = &reference.paths().end { + end_path.relative_encode(ref_end_path, consumer).await?; + } } - } - encode_compact_width_be(start_time_diff, consumer).await?; - encode_compact_width_be(end_time_diff, consumer).await?; + encode_compact_width_be(start_time_diff, consumer).await?; + encode_compact_width_be(end_time_diff, consumer).await?; - Ok(()) + Ok(()) + } } -} -impl - RelativeDecodable> for Range3d -where - S: SubspaceId + Decodable + std::fmt::Debug, -{ - /// Encode an [`Range3d`] relative to another [`Range3d`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. - /// - /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). - async fn relative_decode( - reference: &Range3d, - producer: &mut Producer, - ) -> Result> + impl + RelativeDecodable> for Range3d where - Producer: BulkProducer, - Self: Sized, + S: SubspaceId + Decodable + std::fmt::Debug, { - let header_1 = produce_byte(producer).await?; - - let subspace_start_flags = header_1 & 0b1100_0000; - let subspace_end_flags = header_1 & 0b0011_0000; - let is_path_start_rel_to_start = is_bitflagged(header_1, 4); - let is_path_end_open = is_bitflagged(header_1, 5); - let is_path_end_rel_to_start = is_bitflagged(header_1, 6); - let is_times_end_open = is_bitflagged(header_1, 7); - - let header_2 = produce_byte(producer).await?; - - let is_time_start_rel_to_start = is_bitflagged(header_2, 0); - let add_or_subtract_start_time_diff = is_bitflagged(header_2, 1); - let start_time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header_2, 2); - let is_times_end_rel_to_start = is_bitflagged(header_2, 4); - let add_or_subtract_end_time_diff = is_bitflagged(header_2, 5); - let end_time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header_2, 6); - - // Decode subspace start - let subspace_start = match subspace_start_flags { - 0b0100_0000 => reference.subspaces().start.clone(), - 0b1000_0000 => match &reference.subspaces().end { - RangeEnd::Closed(end) => end.clone(), - RangeEnd::Open => Err(DecodeError::InvalidInput)?, - }, - // This can only be 0b1100_0000 - _ => S::decode(producer).await?, - }; - - let subspace_end = match subspace_end_flags { - 0b0000_0000 => RangeEnd::Open, - 0b0001_0000 => RangeEnd::Closed(reference.subspaces().start.clone()), - 0b0010_0000 => match &reference.subspaces().end { - RangeEnd::Closed(end) => RangeEnd::Closed(end.clone()), - RangeEnd::Open => Err(DecodeError::InvalidInput)?, - }, - // This can only be 0b0011_0000 - _ => RangeEnd::Closed(S::decode(producer).await?), - }; - - let path_start = match (is_path_start_rel_to_start, &reference.paths().end) { - (true, RangeEnd::Closed(_)) => { - Path::relative_decode(&reference.paths().start, producer).await? - } - (true, RangeEnd::Open) => { - Path::relative_decode(&reference.paths().start, producer).await? - } - (false, RangeEnd::Closed(path_end)) => { - Path::relative_decode(path_end, producer).await? - } - (false, RangeEnd::Open) => Err(DecodeError::InvalidInput)?, - }; - - let path_end = if is_path_end_open { - RangeEnd::Open - } else if is_path_end_rel_to_start { - RangeEnd::Closed(Path::relative_decode(&reference.paths().start, producer).await?) - } else { - match &reference.paths().end { - RangeEnd::Closed(end) => { - RangeEnd::Closed(Path::relative_decode(end, producer).await?) + /// Encode an [`Range3d`] relative to another [`Range3d`] which [includes](https://willowprotocol.org/specs/grouping-entries/index.html#area_include_area) it. + /// + /// [Definition](https://willowprotocol.org/specs/encodings/index.html#enc_area_in_area). + async fn relative_decode( + reference: &Range3d, + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let header_1 = produce_byte(producer).await?; + + let subspace_start_flags = header_1 & 0b1100_0000; + let subspace_end_flags = header_1 & 0b0011_0000; + let is_path_start_rel_to_start = is_bitflagged(header_1, 4); + let is_path_end_open = is_bitflagged(header_1, 5); + let is_path_end_rel_to_start = is_bitflagged(header_1, 6); + let is_times_end_open = is_bitflagged(header_1, 7); + + let header_2 = produce_byte(producer).await?; + + let is_time_start_rel_to_start = is_bitflagged(header_2, 0); + let add_or_subtract_start_time_diff = is_bitflagged(header_2, 1); + let start_time_diff_compact_width = + CompactWidth::decode_fixed_width_bitmask(header_2, 2); + let is_times_end_rel_to_start = is_bitflagged(header_2, 4); + let add_or_subtract_end_time_diff = is_bitflagged(header_2, 5); + let end_time_diff_compact_width = CompactWidth::decode_fixed_width_bitmask(header_2, 6); + + // Decode subspace start + let subspace_start = match subspace_start_flags { + 0b0100_0000 => reference.subspaces().start.clone(), + 0b1000_0000 => match &reference.subspaces().end { + RangeEnd::Closed(end) => end.clone(), + RangeEnd::Open => Err(DecodeError::InvalidInput)?, + }, + // This can only be 0b1100_0000 + _ => S::decode(producer).await?, + }; + + let subspace_end = match subspace_end_flags { + 0b0000_0000 => RangeEnd::Open, + 0b0001_0000 => RangeEnd::Closed(reference.subspaces().start.clone()), + 0b0010_0000 => match &reference.subspaces().end { + RangeEnd::Closed(end) => RangeEnd::Closed(end.clone()), + RangeEnd::Open => Err(DecodeError::InvalidInput)?, + }, + // This can only be 0b0011_0000 + _ => RangeEnd::Closed(S::decode(producer).await?), + }; + + let path_start = match (is_path_start_rel_to_start, &reference.paths().end) { + (true, RangeEnd::Closed(_)) => { + Path::relative_decode(&reference.paths().start, producer).await? } - RangeEnd::Open => Err(DecodeError::InvalidInput)?, - } - }; - - let start_time_diff = - decode_compact_width_be(start_time_diff_compact_width, producer).await?; - - let time_start = match (is_time_start_rel_to_start, add_or_subtract_start_time_diff) { - (true, true) => reference.times().start.checked_add(start_time_diff), - (true, false) => reference.times().start.checked_sub(start_time_diff), - (false, true) => match reference.times().end { - RangeEnd::Closed(ref_end) => ref_end.checked_add(start_time_diff), - RangeEnd::Open => Err(DecodeError::InvalidInput)?, - }, - (false, false) => match reference.times().end { - RangeEnd::Closed(ref_end) => ref_end.checked_sub(start_time_diff), - RangeEnd::Open => Err(DecodeError::InvalidInput)?, - }, - } - .ok_or(DecodeError::InvalidInput)?; - - let end_time_diff = decode_compact_width_be(end_time_diff_compact_width, producer).await?; - - let time_end = if is_times_end_open { - RangeEnd::Open - } else { - match (is_times_end_rel_to_start, add_or_subtract_end_time_diff) { - (true, true) => RangeEnd::Closed( - reference - .times() - .start - .checked_add(end_time_diff) - .ok_or(DecodeError::InvalidInput)?, - ), - (true, false) => RangeEnd::Closed( - reference - .times() - .start - .checked_sub(end_time_diff) - .ok_or(DecodeError::InvalidInput)?, - ), + (true, RangeEnd::Open) => { + Path::relative_decode(&reference.paths().start, producer).await? + } + (false, RangeEnd::Closed(path_end)) => { + Path::relative_decode(path_end, producer).await? + } + (false, RangeEnd::Open) => Err(DecodeError::InvalidInput)?, + }; + + let path_end = if is_path_end_open { + RangeEnd::Open + } else if is_path_end_rel_to_start { + RangeEnd::Closed(Path::relative_decode(&reference.paths().start, producer).await?) + } else { + match &reference.paths().end { + RangeEnd::Closed(end) => { + RangeEnd::Closed(Path::relative_decode(end, producer).await?) + } + RangeEnd::Open => Err(DecodeError::InvalidInput)?, + } + }; + + let start_time_diff = + decode_compact_width_be(start_time_diff_compact_width, producer).await?; + + let time_start = match (is_time_start_rel_to_start, add_or_subtract_start_time_diff) { + (true, true) => reference.times().start.checked_add(start_time_diff), + (true, false) => reference.times().start.checked_sub(start_time_diff), (false, true) => match reference.times().end { - RangeEnd::Closed(ref_end) => RangeEnd::Closed( - ref_end - .checked_add(end_time_diff) - .ok_or(DecodeError::InvalidInput)?, - ), + RangeEnd::Closed(ref_end) => ref_end.checked_add(start_time_diff), RangeEnd::Open => Err(DecodeError::InvalidInput)?, }, (false, false) => match reference.times().end { - RangeEnd::Closed(ref_end) => RangeEnd::Closed( - ref_end + RangeEnd::Closed(ref_end) => ref_end.checked_sub(start_time_diff), + RangeEnd::Open => Err(DecodeError::InvalidInput)?, + }, + } + .ok_or(DecodeError::InvalidInput)?; + + let end_time_diff = + decode_compact_width_be(end_time_diff_compact_width, producer).await?; + + let time_end = if is_times_end_open { + RangeEnd::Open + } else { + match (is_times_end_rel_to_start, add_or_subtract_end_time_diff) { + (true, true) => RangeEnd::Closed( + reference + .times() + .start + .checked_add(end_time_diff) + .ok_or(DecodeError::InvalidInput)?, + ), + (true, false) => RangeEnd::Closed( + reference + .times() + .start .checked_sub(end_time_diff) .ok_or(DecodeError::InvalidInput)?, ), - RangeEnd::Open => Err(DecodeError::InvalidInput)?, + (false, true) => match reference.times().end { + RangeEnd::Closed(ref_end) => RangeEnd::Closed( + ref_end + .checked_add(end_time_diff) + .ok_or(DecodeError::InvalidInput)?, + ), + RangeEnd::Open => Err(DecodeError::InvalidInput)?, + }, + (false, false) => match reference.times().end { + RangeEnd::Closed(ref_end) => RangeEnd::Closed( + ref_end + .checked_sub(end_time_diff) + .ok_or(DecodeError::InvalidInput)?, + ), + RangeEnd::Open => Err(DecodeError::InvalidInput)?, + }, + } + }; + + Ok(Self::new( + Range { + start: subspace_start, + end: subspace_end, }, - } - }; - - Ok(Self::new( - Range { - start: subspace_start, - end: subspace_end, - }, - Range { - start: path_start, - end: path_end, - }, - Range { - start: time_start, - end: time_end, - }, - )) + Range { + start: path_start, + end: path_end, + }, + Range { + start: time_start, + end: time_end, + }, + )) + } } } diff --git a/data-model/src/encoding/unsigned_int.rs b/data-model/src/encoding/unsigned_int.rs index edbd2ab..e55ad1b 100644 --- a/data-model/src/encoding/unsigned_int.rs +++ b/data-model/src/encoding/unsigned_int.rs @@ -1,39 +1,11 @@ -use core::mem::size_of; -use ufotofu::local_nb::{BulkConsumer, BulkProducer}; - use crate::encoding::error::DecodeError; -use crate::encoding::parameters::{Decodable, Encodable}; + +use core::mem::size_of; /// A `u8` wrapper that implements [`Encoding`] and [`Decoding`] by encoding as a big-endian fixed-width integer. #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct U8BE(u8); -impl Encodable for U8BE { - async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> - where - Consumer: BulkConsumer, - { - let byte = self.0.to_be_bytes(); - consumer - .bulk_consume_full_slice(&byte) - .await - .map_err(|f| f.reason)?; - Ok(()) - } -} - -impl Decodable for U8BE { - async fn decode(producer: &mut Producer) -> Result> - where - Producer: BulkProducer, - Self: Sized, - { - let mut bytes = [0u8; size_of::()]; - producer.bulk_overwrite_full_slice(&mut bytes).await?; - Ok(U8BE(u8::from_be_bytes(bytes))) - } -} - impl From for U8BE { fn from(value: u8) -> Self { Self(value) @@ -50,32 +22,6 @@ impl From for u64 { #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct U16BE(u16); -impl Encodable for U16BE { - async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> - where - Consumer: BulkConsumer, - { - let bytes = self.0.to_be_bytes(); - consumer - .bulk_consume_full_slice(&bytes) - .await - .map_err(|f| f.reason)?; - Ok(()) - } -} - -impl Decodable for U16BE { - async fn decode(producer: &mut Producer) -> Result> - where - Producer: BulkProducer, - Self: Sized, - { - let mut bytes = [0u8; size_of::()]; - producer.bulk_overwrite_full_slice(&mut bytes).await?; - Ok(U16BE(u16::from_be_bytes(bytes))) - } -} - impl From for U16BE { fn from(value: u16) -> Self { Self(value) @@ -92,32 +38,6 @@ impl From for u64 { #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct U32BE(u32); -impl Encodable for U32BE { - async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> - where - Consumer: BulkConsumer, - { - let bytes = self.0.to_be_bytes(); - consumer - .bulk_consume_full_slice(&bytes) - .await - .map_err(|f| f.reason)?; - Ok(()) - } -} - -impl Decodable for U32BE { - async fn decode(producer: &mut Producer) -> Result> - where - Producer: BulkProducer, - Self: Sized, - { - let mut bytes = [0u8; size_of::()]; - producer.bulk_overwrite_full_slice(&mut bytes).await?; - Ok(U32BE(u32::from_be_bytes(bytes))) - } -} - impl From for U32BE { fn from(value: u32) -> Self { Self(value) @@ -134,32 +54,6 @@ impl From for u64 { #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct U64BE(u64); -impl Encodable for U64BE { - async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> - where - Consumer: BulkConsumer, - { - let bytes = self.0.to_be_bytes(); - consumer - .bulk_consume_full_slice(&bytes) - .await - .map_err(|f| f.reason)?; - Ok(()) - } -} - -impl Decodable for U64BE { - async fn decode(producer: &mut Producer) -> Result> - where - Producer: BulkProducer, - Self: Sized, - { - let mut bytes = [0u8; size_of::()]; - producer.bulk_overwrite_full_slice(&mut bytes).await?; - Ok(U64BE(u64::from_be_bytes(bytes))) - } -} - impl From for U64BE { fn from(value: u64) -> Self { Self(value) @@ -171,3 +65,129 @@ impl From for u64 { value.0 } } + +use syncify::syncify; +use syncify::syncify_replace; + +#[syncify(encoding_sync)] +mod encoding { + use super::*; + + #[syncify_replace(use ufotofu::sync::{BulkConsumer, BulkProducer};)] + use ufotofu::local_nb::{BulkConsumer, BulkProducer}; + + #[syncify_replace(use crate::encoding::parameters_sync::{Decodable, Encodable};)] + use crate::encoding::parameters::{Decodable, Encodable}; + + impl Encodable for U8BE { + async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let byte = self.0.to_be_bytes(); + consumer + .bulk_consume_full_slice(&byte) + .await + .map_err(|f| f.reason)?; + Ok(()) + } + } + + impl Decodable for U8BE { + async fn decode( + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let mut bytes = [0u8; size_of::()]; + producer.bulk_overwrite_full_slice(&mut bytes).await?; + Ok(U8BE(u8::from_be_bytes(bytes))) + } + } + + impl Encodable for U16BE { + async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let bytes = self.0.to_be_bytes(); + consumer + .bulk_consume_full_slice(&bytes) + .await + .map_err(|f| f.reason)?; + Ok(()) + } + } + + impl Decodable for U16BE { + async fn decode( + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let mut bytes = [0u8; size_of::()]; + producer.bulk_overwrite_full_slice(&mut bytes).await?; + Ok(U16BE(u16::from_be_bytes(bytes))) + } + } + + impl Encodable for U32BE { + async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let bytes = self.0.to_be_bytes(); + consumer + .bulk_consume_full_slice(&bytes) + .await + .map_err(|f| f.reason)?; + Ok(()) + } + } + + impl Decodable for U32BE { + async fn decode( + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let mut bytes = [0u8; size_of::()]; + producer.bulk_overwrite_full_slice(&mut bytes).await?; + Ok(U32BE(u32::from_be_bytes(bytes))) + } + } + + impl Encodable for U64BE { + async fn encode(&self, consumer: &mut Consumer) -> Result<(), Consumer::Error> + where + Consumer: BulkConsumer, + { + let bytes = self.0.to_be_bytes(); + consumer + .bulk_consume_full_slice(&bytes) + .await + .map_err(|f| f.reason)?; + Ok(()) + } + } + + impl Decodable for U64BE { + async fn decode( + producer: &mut Producer, + ) -> Result> + where + Producer: BulkProducer, + Self: Sized, + { + let mut bytes = [0u8; size_of::()]; + producer.bulk_overwrite_full_slice(&mut bytes).await?; + Ok(U64BE(u64::from_be_bytes(bytes))) + } + } +} diff --git a/data-model/src/entry.rs b/data-model/src/entry.rs index 5f50f8d..fe6eed6 100644 --- a/data-model/src/entry.rs +++ b/data-model/src/entry.rs @@ -2,14 +2,9 @@ use arbitrary::size_hint::and_all; #[cfg(feature = "dev")] use arbitrary::Arbitrary; -use ufotofu::local_nb::{BulkConsumer, BulkProducer}; use crate::{ - encoding::{ - error::DecodeError, - parameters::{Decodable, Encodable}, - unsigned_int::U64BE, - }, + encoding::{error::DecodeError, unsigned_int::U64BE}, parameters::{IsAuthorisedWrite, NamespaceId, PayloadDigest, SubspaceId}, path::Path, }; @@ -116,56 +111,70 @@ where } } -impl Encodable - for Entry -where - N: NamespaceId + Encodable, - S: SubspaceId + Encodable, - PD: PayloadDigest + Encodable, -{ - async fn encode(&self, consumer: &mut C) -> Result<(), ::Error> +use syncify::syncify; +use syncify::syncify_replace; + +#[syncify(encoding_sync)] +mod encoding { + use super::*; + + #[syncify_replace(use ufotofu::sync::{BulkConsumer, BulkProducer};)] + use ufotofu::local_nb::{BulkConsumer, BulkProducer}; + + #[syncify_replace(use crate::encoding::parameters_sync::{Decodable, Encodable};)] + use crate::encoding::parameters::{Decodable, Encodable}; + + impl Encodable + for Entry where - C: BulkConsumer, + N: NamespaceId + Encodable, + S: SubspaceId + Encodable, + PD: PayloadDigest + Encodable, { - self.namespace_id.encode(consumer).await?; - self.subspace_id.encode(consumer).await?; - self.path.encode(consumer).await?; + async fn encode(&self, consumer: &mut C) -> Result<(), ::Error> + where + C: BulkConsumer, + { + self.namespace_id.encode(consumer).await?; + self.subspace_id.encode(consumer).await?; + self.path.encode(consumer).await?; - U64BE::from(self.timestamp).encode(consumer).await?; - U64BE::from(self.payload_length).encode(consumer).await?; + U64BE::from(self.timestamp).encode(consumer).await?; + U64BE::from(self.payload_length).encode(consumer).await?; - self.payload_digest.encode(consumer).await?; + self.payload_digest.encode(consumer).await?; - Ok(()) + Ok(()) + } } -} -impl Decodable - for Entry -where - N: NamespaceId + Decodable, - S: SubspaceId + Decodable, - PD: PayloadDigest + Decodable, -{ - async fn decode(producer: &mut Prod) -> Result> + impl Decodable + for Entry where - Prod: BulkProducer, + N: NamespaceId + Decodable, + S: SubspaceId + Decodable, + PD: PayloadDigest + Decodable, { - let namespace_id = N::decode(producer).await?; - let subspace_id = S::decode(producer).await?; - let path = Path::::decode(producer).await?; - let timestamp = U64BE::decode(producer).await?.into(); - let payload_length = U64BE::decode(producer).await?.into(); - let payload_digest = PD::decode(producer).await?; - - Ok(Entry { - namespace_id, - subspace_id, - path, - timestamp, - payload_length, - payload_digest, - }) + async fn decode(producer: &mut Prod) -> Result> + where + Prod: BulkProducer, + { + let namespace_id = N::decode(producer).await?; + let subspace_id = S::decode(producer).await?; + let path = Path::::decode(producer).await?; + let timestamp = U64BE::decode(producer).await?.into(); + let payload_length = U64BE::decode(producer).await?.into(); + let payload_digest = PD::decode(producer).await?; + + Ok(Entry { + namespace_id, + subspace_id, + path, + timestamp, + payload_length, + payload_digest, + }) + } } } diff --git a/fuzz/src/encode.rs b/fuzz/src/encode.rs index a5b4def..6210c25 100644 --- a/fuzz/src/encode.rs +++ b/fuzz/src/encode.rs @@ -9,8 +9,7 @@ use ufotofu::{ use willow_data_model::encoding::{ error::DecodeError, - parameters::{Decodable, Encodable}, - relativity::{RelativeDecodable, RelativeEncodable}, + parameters::{Decodable, Encodable, RelativeDecodable, RelativeEncodable}, }; pub async fn encoding_roundtrip(item: T, consumer: &mut TestConsumer)