diff --git a/Cargo.toml b/Cargo.toml index 694fde2..c994cf2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,25 +39,16 @@ authors.workspace = true [features] default = [] -bytes = ["dep:bytes"] -encode = ["dep:unsigned-varint", "dep:varint-simd"] -serde = ["encode", "dep:serde"] +serde = ["dep:serde"] [dependencies] fxhash = "0.2" -bytes = { version = "1", optional = true } serde = { version = "1", optional = true, features = ["derive"] } -[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] -varint-simd = { version = "0.4", optional = true } - -[target.'cfg(not(any(target_arch = "x86", target_arch = "x86_64")))'.dependencies] -unsigned-varint = { version = "0.8", optional = true } - [dev-dependencies] bincode = { version = "2", features = ["serde"] } criterion = "0.7" -pando = { path = ".", features = ["encode", "serde"] } +pando = { path = ".", features = ["serde"] } pando-macros = { path = "macros" } rand = "0.9" rand_chacha = "0.9" @@ -71,11 +62,6 @@ harness = false name = "apply_remote" harness = false -[[bench]] -name = "encode" -harness = false -required-features = ["encode"] - [[bench]] name = "serde" harness = false diff --git a/benches/encode.rs b/benches/encode.rs deleted file mode 100644 index 6d37913..0000000 --- a/benches/encode.rs +++ /dev/null @@ -1,141 +0,0 @@ -#![allow(missing_docs)] -#![allow(clippy::unwrap_used)] - -mod common; - -use core::fmt; - -use common::TreeSize; -use criterion::{BenchmarkId, Criterion}; -use pando::encode::{Buffer, Decode, Encode}; -use rand::SeedableRng; - -fn bench_encode(c: &mut Criterion) { - let mut rng = ::seed_from_u64(42); - - let mut group = c.benchmark_group(format!("encode_{}", M::NAME)); - - for test_vector in TestVector::iter() { - let tree = test_vector.tree_size.to_tree::(&mut rng); - group.bench_function(test_vector.bench_id(), |bencher| { - bencher.iter(|| { - if test_vector.encode_tree_state { - tree.encode::() - } else { - tree.encode::() - } - }) - }); - } -} - -fn bench_decode(c: &mut Criterion) { - let mut rng = ::seed_from_u64(42); - - let mut group = c.benchmark_group(format!("decode_{}", M::NAME)); - - for test_vector in TestVector::iter() { - let tree = test_vector.tree_size.to_tree::(&mut rng); - let encoded = if test_vector.encode_tree_state { - tree.encode::() - } else { - tree.encode::() - }; - group.bench_function(test_vector.bench_id(), |bencher| { - bencher.iter(|| { - pando::Tree::::decode(&mut &*encoded, 2).unwrap(); - }) - }); - } -} - -trait Metadata: - Default + Clone + fmt::Debug + Eq + Encode + Decode -{ - const NAME: &str; -} - -#[derive(Debug, Clone, PartialEq, Eq)] -struct LargeString { - inner: String, -} - -struct TestVector { - encode_tree_state: bool, - tree_size: TreeSize, -} - -impl TestVector { - fn iter() -> impl Iterator { - let mut items = Vec::new(); - - for tree_size in TreeSize::iter() { - for encode_tree_state in [true, false] { - items.push(Self { encode_tree_state, tree_size }); - } - } - - items.into_iter() - } - - fn bench_id(&self) -> BenchmarkId { - BenchmarkId::new( - self.tree_size, - if self.encode_tree_state { - "with_state" - } else { - "without_state" - }, - ) - } -} - -impl Metadata for () { - const NAME: &str = "unit"; -} - -impl Metadata for LargeString { - const NAME: &str = "large_string"; -} - -impl Default for LargeString { - fn default() -> Self { - Self { inner: "x".repeat(SIZE) } - } -} - -impl Encode for LargeString { - #[inline] - fn encode(&self, encoder: &mut impl Buffer) { - self.inner.as_str().encode(encoder); - } -} - -impl Decode for LargeString { - type Error = ::Error; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - String::decode(buf).map(|inner| Self { inner }) - } -} - -fn encode_unit(c: &mut Criterion) { - bench_encode::<()>(c); -} - -fn encode_large_string(c: &mut Criterion) { - bench_encode::(c); -} - -fn decode_unit(c: &mut Criterion) { - bench_decode::<()>(c); -} - -fn decode_large_string(c: &mut Criterion) { - bench_decode::(c); -} - -criterion::criterion_group!(encode, encode_unit, encode_large_string); -criterion::criterion_group!(decode, decode_unit, decode_large_string); -criterion::criterion_main!(encode, decode); diff --git a/src/encode.rs b/src/encode.rs deleted file mode 100644 index 2dd1bf9..0000000 --- a/src/encode.rs +++ /dev/null @@ -1,743 +0,0 @@ -//! TODO: docs. - -use core::fmt; -use core::hash::{BuildHasher, Hash}; -use core::mem::{self, MaybeUninit}; -use std::collections::HashMap; - -use crate::ProtocolVersion; - -/// TODO: docs. -pub trait Buffer { - /// TODO: docs. - fn extend(&mut self, bytes: &[u8]); - - /// TODO: docs. - #[inline] - fn push(&mut self, byte: u8) { - self.extend(&[byte]); - } -} - -/// TODO: docs. -pub trait Encode { - /// TODO: docs. - fn encode(&self, buf: &mut impl Buffer); -} - -/// TODO: docs. -pub trait Decode: Sized { - /// TODO: docs. - type Error; - - /// TODO: docs. - fn decode(buf: &mut &[u8]) -> Result; -} - -/// The type of error that can occur when [`decode`](crate::Tree::decode)ing a -/// `Tree`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum DecodeError { - /// TODO: docs. - InvalidData, - - /// Some metadata couldn't be decoded. - Metadata(M), - - /// This error occurs when the machine that - /// [`encode`](crate::Tree::encode)d a `Tree` and the one that is trying to - /// [`decode`](crate::Tree::decode) it are using two incompatible versions - /// of pando. - ProtocolMismatch { - /// The `ProtocolVersion` of pando on the machine that encoded the - /// `Tree`. - encoded_on: ProtocolVersion, - - /// The `ProtocolVersion` of pando on the machine that is trying to - /// decode the encoded buffer. - decoding_on: ProtocolVersion, - }, -} - -/// The type of error that can occur when decoding a -/// [`Creation`](crate::ops::Creation). -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum CreationDecodeError { - /// The creation's [node ID](crate::ops::Creation::node_id) or - /// [parent ID](crate::ops::Creation::parent_id) could not be decoded. - Int(IntDecodeError), - - /// The creations's metadata could not be decoded. - Metadata(T), -} - -/// The type of error that can occur when decoding a `bool`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum BoolDecodeError { - /// The buffer was empty. - EmptyBuffer, - - /// The first byte of the buffer was not a 0 or 1. - InvalidByte(u8), -} - -/// The type of error that can occur when decoding a `u8`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum ByteDecodeError { - /// The buffer was empty. - EmptyBuffer, -} - -/// The type of error that can occur when decoding an integer fails. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct IntDecodeError { - inner: crate::leb128::DecodeError, -} - -/// The type of error that can occur when decoding an `Option` fails. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum OptionDecodeError { - /// The option's tag could not be decoded. - Tag(BoolDecodeError), - - /// The value could not be decoded. - Value(T), -} - -/// The type of error that can occur when decoding a `Vec` fails. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum VecDecodeError { - /// The vector's length could not be decoded. - Length(IntDecodeError), - - /// An item could not be decoded. - Item(T), -} - -/// The type of error that can occur when decoding a `HashMap` fails. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum HashMapDecodeError { - /// The maps's length could not be decoded. - Length(IntDecodeError), - - /// A key could not be decoded. - Key(K), - - /// A value could not be decoded. - Value(V), -} - -/// The type of error that can occur when decoding a `String` fails. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum StringDecodeError { - /// The string's length could not be decoded. - Length(IntDecodeError), - - /// The buffer did not contain enough bytes to decode the string. - NotEnoughBytes, - - /// The buffer contained non-UTF-8 bytes. - Utf8(alloc::string::FromUtf8Error), -} - -impl Buffer for Vec { - #[inline] - fn extend(&mut self, bytes: &[u8]) { - self.extend_from_slice(bytes); - } -} - -impl Encode for &T { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - (*self).encode(buf); - } -} - -impl Encode for () { - #[inline] - fn encode(&self, _: &mut impl Buffer) {} -} - -impl Decode for () { - type Error = core::convert::Infallible; - - #[inline] - fn decode(_: &mut &[u8]) -> Result { - Ok(()) - } -} - -impl Encode for bool { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - (*self as u8).encode(buf); - } -} - -impl Decode for bool { - type Error = BoolDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let byte = u8::decode(buf)?; - if byte > 1 { - return Err(BoolDecodeError::InvalidByte(byte)); - } - Ok(byte == 1) - } -} - -impl Encode for u8 { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - buf.push(*self); - } -} - -impl Decode for u8 { - type Error = ByteDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let (&first, rest) = - buf.split_first().ok_or(ByteDecodeError::EmptyBuffer)?; - *buf = rest; - Ok(first) - } -} - -macro_rules! impl_int_encode { - ($int:ty, $encode_fn:ident) => { - impl Encode for $int { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - let (array, len) = crate::leb128::$encode_fn(*self); - buf.extend(&array[..len as usize]); - } - } - }; -} - -impl_int_encode!(u16, encode_u16); -impl_int_encode!(u32, encode_u32); -impl_int_encode!(u64, encode_u64); - -macro_rules! impl_int_decode { - ($int:ty, $decode_fn:ident) => { - impl Decode for $int { - type Error = IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let (decoded, len) = crate::leb128::$decode_fn(buf)?; - *buf = &buf[len as usize..]; - Ok(decoded) - } - } - }; -} - -impl_int_decode!(u16, decode_u16); -impl_int_decode!(u32, decode_u32); -impl_int_decode!(u64, decode_u64); - -impl Encode for Option { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - if let Some(value) = self { - true.encode(buf); - value.encode(buf); - } else { - false.encode(buf); - } - } -} - -impl Decode for Option { - type Error = OptionDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let is_some = bool::decode(buf).map_err(OptionDecodeError::Tag)?; - if is_some { - let value = T::decode(buf).map_err(OptionDecodeError::Value)?; - Ok(Some(value)) - } else { - Ok(None) - } - } -} - -/// # Panics -/// -/// Panics if the slice's length is greater than `u64::MAX`. -impl Encode for &[u8] { - #[track_caller] - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - match u64::try_from(self.len()) { - Ok(len) => len.encode(buf), - Err(_) => panic!("slice length exceeds u64::MAX"), - } - buf.extend(self); - } -} - -/// # Panics -/// -/// Panics if the string's length is greater than `u64::MAX`. -impl Encode for &str { - #[track_caller] - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.as_bytes().encode(buf); - } -} - -impl Encode for Vec { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - // Vecs can only contain up to isize::MAX items, so it's ok to cast the - // length to a u64. - (self.len() as u64).encode(buf); - for item in self { - item.encode(buf); - } - } -} - -impl Decode for Vec { - type Error = VecDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let len = u64::decode(buf).map_err(VecDecodeError::Length)?; - let mut vec = Vec::with_capacity(len as usize); - for _ in 0..len { - let item = T::decode(buf).map_err(VecDecodeError::Item)?; - vec.push(item); - } - Ok(vec) - } -} - -impl Encode for [T; N] { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - for item in self { - item.encode(buf); - } - } -} - -impl Decode for [T; N] { - type Error = T::Error; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - // TODO: replace this with `MaybeUninit::uninit_array` when it's - // stabilized. - let mut array: [MaybeUninit; N] = - unsafe { mem::MaybeUninit::uninit().assume_init() }; - - let mut num_initialized = 0; - - while num_initialized < N { - match T::decode(buf) { - Ok(item) => { - array[num_initialized] = MaybeUninit::new(item); - num_initialized += 1; - }, - Err(err) => { - // SAFETY: the first `num_initialized` items in the array - // have been initialized. - for item in &mut array[..num_initialized] { - unsafe { item.assume_init_drop() }; - } - return Err(err); - }, - }; - } - - // SAFETY: all the items in the array have been initialized. - // - // TODO: replace this with `MaybeUninit::array_assume_init` when it's - // stabilized. - let array = unsafe { - (&array as *const [MaybeUninit; N] as *const [T; N]).read() - }; - - Ok(array) - } -} - -/// # Panics -/// -/// Panics if the length of the `HashMap` is greater than `u64::MAX`. -impl Encode for HashMap { - #[track_caller] - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - match u64::try_from(self.len()) { - Ok(len) => len.encode(buf), - Err(_) => panic!("HashMap length exceeds u64::MAX"), - } - - for (key, value) in self.iter() { - key.encode(buf); - value.encode(buf); - } - } -} - -impl Decode for HashMap -where - K: Eq + Hash + Decode, - V: Decode, - H: Default + BuildHasher, -{ - type Error = HashMapDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let len = u64::decode(buf).map_err(HashMapDecodeError::Length)?; - let mut map = - HashMap::with_capacity_and_hasher(len as usize, H::default()); - for _ in 0..len { - let key = K::decode(buf).map_err(HashMapDecodeError::Key)?; - let value = V::decode(buf).map_err(HashMapDecodeError::Value)?; - map.insert(key, value); - } - Ok(map) - } -} - -impl Decode for String { - type Error = StringDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - Vec::::decode(buf) - .map_err(|err| match err { - VecDecodeError::Length(err) => StringDecodeError::Length(err), - VecDecodeError::Item(_) => StringDecodeError::NotEnoughBytes, - }) - .and_then(|vec| { - String::from_utf8(vec).map_err(StringDecodeError::Utf8) - }) - } -} - -impl fmt::Display for DecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::InvalidData => f.write_str("invalid data"), - Self::Metadata(metadata) => fmt::Display::fmt(metadata, f), - Self::ProtocolMismatch { encoded_on, decoding_on } => { - write!( - f, - "protocol mismatch: encoded on {encoded_on}, decoding on \ - {decoding_on}", - ) - }, - } - } -} - -impl core::error::Error for DecodeError { - #[inline] - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Self::InvalidData => None, - Self::Metadata(err) => err.source(), - Self::ProtocolMismatch { .. } => None, - } - } -} - -impl fmt::Display for CreationDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Int(err) => fmt::Display::fmt(err, f), - Self::Metadata(err) => fmt::Display::fmt(err, f), - } - } -} - -impl core::error::Error for CreationDecodeError { - #[inline] - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Self::Int(err) => err.source(), - Self::Metadata(err) => err.source(), - } - } -} - -impl From for BoolDecodeError { - #[inline] - fn from(err: ByteDecodeError) -> Self { - match err { - ByteDecodeError::EmptyBuffer => Self::EmptyBuffer, - } - } -} - -impl From> for BoolDecodeError -where - Err: Into, -{ - #[inline] - fn from(err: OptionDecodeError) -> Self { - match err { - OptionDecodeError::Tag(tag_err) => tag_err, - OptionDecodeError::Value(value_err) => value_err.into(), - } - } -} - -impl fmt::Display for BoolDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::EmptyBuffer => f.write_str("empty buffer"), - Self::InvalidByte(byte) => { - write!(f, "invalid byte: {byte}, expected 0 or 1") - }, - } - } -} - -impl core::error::Error for BoolDecodeError {} - -impl fmt::Display for ByteDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::EmptyBuffer => f.write_str("empty buffer"), - } - } -} - -impl core::error::Error for ByteDecodeError {} - -impl From for IntDecodeError { - #[inline] - fn from(inner: crate::leb128::DecodeError) -> Self { - Self { inner } - } -} - -impl fmt::Display for IntDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.inner, f) - } -} - -impl core::error::Error for IntDecodeError { - #[inline] - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - Some(&self.inner) - } -} - -impl> From> for IntDecodeError { - #[inline] - fn from(err: VecDecodeError) -> Self { - match err { - VecDecodeError::Length(len_err) => len_err, - VecDecodeError::Item(item_err) => item_err.into(), - } - } -} - -impl From> for IntDecodeError -where - K: Into, - V: Into, -{ - #[inline] - fn from(err: HashMapDecodeError) -> Self { - match err { - HashMapDecodeError::Length(len_err) => len_err, - HashMapDecodeError::Key(key_err) => key_err.into(), - HashMapDecodeError::Value(value_err) => value_err.into(), - } - } -} - -impl fmt::Display for OptionDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Tag(err) => fmt::Display::fmt(err, f), - Self::Value(err) => fmt::Display::fmt(err, f), - } - } -} - -impl core::error::Error for OptionDecodeError { - #[inline] - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - match self { - Self::Tag(err) => err.source(), - Self::Value(err) => err.source(), - } - } -} - -impl fmt::Display for VecDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Length(err) => fmt::Display::fmt(err, f), - Self::Item(err) => fmt::Display::fmt(err, f), - } - } -} - -impl core::error::Error for VecDecodeError { - #[inline] - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - match self { - Self::Length(err) => err.source(), - Self::Item(err) => err.source(), - } - } -} - -impl fmt::Display for HashMapDecodeError -where - K: fmt::Display, - V: fmt::Display, -{ - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Length(err) => fmt::Display::fmt(err, f), - Self::Key(err) => fmt::Display::fmt(err, f), - Self::Value(err) => fmt::Display::fmt(err, f), - } - } -} - -impl fmt::Display for StringDecodeError { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Length(err) => fmt::Display::fmt(err, f), - Self::NotEnoughBytes => { - f.write_str("not enough bytes to decode string") - }, - Self::Utf8(err) => fmt::Display::fmt(err, f), - } - } -} - -impl core::error::Error for StringDecodeError { - #[inline] - fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { - match self { - Self::Length(err) => err.source(), - Self::NotEnoughBytes => None, - Self::Utf8(err) => err.source(), - } - } -} - -#[cfg(feature = "bytes")] -#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))] -impl Buffer for bytes::BytesMut { - #[inline] - fn extend(&mut self, bytes: &[u8]) { - self.extend_from_slice(bytes); - } -} - -#[cfg(feature = "serde")] -pub use serde::SerdeCompat; - -#[cfg(feature = "serde")] -mod serde { - use core::marker::PhantomData; - - use ::serde::{de, ser}; - - use super::*; - - /// TODO: docs. - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - pub struct SerdeCompat(pub T); - - impl ser::Serialize for SerdeCompat { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: ser::Serializer, - { - let Self(inner) = self; - let mut buf = Vec::new(); - inner.encode(&mut buf); - serializer.serialize_bytes(&buf) - } - } - - impl<'de, T> de::Deserialize<'de> for SerdeCompat - where - T: Decode, - { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - struct Visitor(PhantomData); - - impl<'de, T> ::serde::de::Visitor<'de> for Visitor - where - T: Decode, - { - type Value = T; - - #[inline] - fn expecting( - &self, - formatter: &mut ::core::fmt::Formatter, - ) -> ::core::fmt::Result { - formatter.write_str("a byte slice") - } - - #[inline] - fn visit_bytes(self, mut v: &[u8]) -> Result - where - E: ::serde::de::Error, - { - T::decode(&mut v).map_err(E::custom) - } - - #[inline] - fn visit_seq( - self, - mut seq: A, - ) -> Result - where - A: de::SeqAccess<'de>, - { - let size = seq.size_hint().unwrap_or(0); - let mut buf = Vec::::with_capacity(size); - while let Some(byte) = seq.next_element()? { - buf.push(byte); - } - T::decode(&mut &*buf) - .map_err(::custom) - } - } - - deserializer.deserialize_bytes(Visitor(PhantomData::)).map(Self) - } - } -} diff --git a/src/forest.rs b/src/forest.rs index 4647c4e..15e7f8f 100644 --- a/src/forest.rs +++ b/src/forest.rs @@ -1010,116 +1010,3 @@ mod debug { } } } - -#[cfg(feature = "encode")] -mod encode { - use super::*; - use crate::encode::{self, Buffer, Decode, Encode}; - - impl Encode for Forest { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.nodes.encode(buf); - self.backlog.encode(buf); - self.id_to_key.encode(buf); - } - } - - impl Decode for Forest { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let forest = Vec::decode(buf)?; - let backlog = Backlog::decode(buf)?; - let id_to_key = FxHashMap::decode(buf)?; - Ok(Self { nodes: forest, backlog, id_to_key }) - } - } - - impl Encode for Node { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.children.encode(buf); - self.creation_key.encode(buf); - self.parent_key.encode(buf); - } - } - - impl Decode for Node { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let children = Vec::decode(buf)?; - let creation_key = op_log::OpKey::decode(buf)?; - let parent_key = NodeKey::decode(buf)?; - Ok(Self { children, creation_key, parent_key }) - } - } - - impl Encode for NodeKey { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - // NodeKey is a newtype around an index into a Vec, and Vecs can - // only contain up to isize::MAX items, so it's ok to cast it to a - // u64. - (self.0 as u64).encode(buf); - } - } - - impl Decode for NodeKey { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - u64::decode(buf).map(|inner| Self(inner as usize)) - } - } - - impl Encode for udr::PrevParent { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - match *self { - Self::Backlogged => NodeKey::NONE_BACKLOGGED, - Self::Origin => NodeKey::NONE_VISIBLE, - Self::OpIsNoOp => NodeKey::NONE_DELETED, - Self::Node(LocalNodeId { forest_key: tree_key }) => tree_key, - } - .encode(buf); - } - } - - impl Decode for udr::PrevParent { - type Error = ::Error; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - Ok(match NodeKey::decode(buf)? { - NodeKey::NONE_BACKLOGGED => Self::Backlogged, - NodeKey::NONE_VISIBLE => Self::Origin, - NodeKey::NONE_DELETED => Self::OpIsNoOp, - node_key => Self::Node(LocalNodeId::new(node_key)), - }) - } - } - - impl Encode for Backlog { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.id_to_keys.encode(buf); - self.key_to_id.encode(buf); - } - } - - impl Decode for Backlog { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let id_to_keys = FxHashMap::decode(buf)?; - let key_to_id = FxHashMap::decode(buf)?; - Ok(Self { key_to_id, id_to_keys }) - } - } -} diff --git a/src/gtree.rs b/src/gtree.rs index 0e53428..025de5b 100644 --- a/src/gtree.rs +++ b/src/gtree.rs @@ -1444,248 +1444,6 @@ pub(crate) mod gtree_iter { } } -#[cfg(feature = "encode")] -pub(crate) use gtree_encode::GtreeDecodeError; - -#[cfg(feature = "encode")] -mod gtree_encode { - use super::*; - use crate::encode::{self, Buffer, Decode, Encode}; - - pub(crate) enum GtreeDecodeError - where - T: Decode, - T::Summary: Decode, - { - Bool(encode::BoolDecodeError), - Int(encode::IntDecodeError), - Item(::Error), - Summary(::Error), - } - - pub(super) enum InodeDecodeError { - Bool(encode::BoolDecodeError), - Int(encode::IntDecodeError), - Summary(T), - } - - pub(super) enum LeafDecodeError { - Item(T), - Int(encode::IntDecodeError), - } - - impl Encode for Gtree - where - T: Encode, - T::Summary: Encode, - { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.inodes.encode(buf); - self.leaves.encode(buf); - self.root_idx.encode(buf); - } - } - - impl Decode for Gtree - where - T: Decode, - T::Summary: Decode, - { - type Error = GtreeDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let inodes = Vec::>::decode(buf).map_err( - |err| match err { - encode::VecDecodeError::Length(err) => { - GtreeDecodeError::Int(err) - }, - encode::VecDecodeError::Item(err) => err.into(), - }, - )?; - - let leaves = - Vec::>::decode(buf).map_err(|err| match err { - encode::VecDecodeError::Length(err) => { - GtreeDecodeError::Int(err) - }, - encode::VecDecodeError::Item(err) => err.into(), - })?; - - let root_idx = - InodeIdx::decode(buf).map_err(GtreeDecodeError::Int)?; - - Ok(Self { inodes, leaves, root_idx }) - } - } - - impl Encode for Key { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.0.encode(buf); - } - } - - impl Decode for Key { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - LeafIdx::decode(buf).map(Self) - } - } - - impl Encode for Inode - where - T: Encode, - T::Summary: Encode, - { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.children.encode(buf); - self.children_are_leaves.encode(buf); - self.max_summary.encode(buf); - self.num_children.encode(buf); - self.parent_idx.encode(buf); - } - } - - impl Decode for Inode - where - T::Summary: Decode, - { - type Error = InodeDecodeError<::Error>; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let children = <[NodeIdx; FANOUT]>::decode(buf) - .map_err(InodeDecodeError::Int)?; - - let children_are_leaves = - bool::decode(buf).map_err(InodeDecodeError::Bool)?; - - let max_summary = - T::Summary::decode(buf).map_err(InodeDecodeError::Summary)?; - - let num_children = - Fanout::decode(buf).map_err(InodeDecodeError::Int)?; - - let parent_idx = - InodeIdx::decode(buf).map_err(InodeDecodeError::Int)?; - - Ok(Self { - children, - children_are_leaves, - max_summary, - num_children, - parent_idx, - }) - } - } - - impl Encode for Leaf { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.item.encode(buf); - self.parent_idx.encode(buf); - } - } - - impl Decode for Leaf { - type Error = LeafDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let item = T::decode(buf).map_err(LeafDecodeError::Item)?; - let parent_idx = - InodeIdx::decode(buf).map_err(LeafDecodeError::Int)?; - Ok(Self { item, parent_idx }) - } - } - - impl Encode for InodeIdx { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.0.encode(buf); - } - } - - impl Decode for InodeIdx { - type Error = ::Error; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - NodeIdx::decode(buf).map(Self) - } - } - - impl Encode for LeafIdx { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.0.encode(buf); - } - } - - impl Decode for LeafIdx { - type Error = ::Error; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - NodeIdx::decode(buf).map(Self) - } - } - - impl Encode for NodeIdx { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - // NodeIdx is a newtype around an index into a Vec, and Vecs can - // only contain up to isize::MAX items, so it's ok to cast it to a - // u64. - (self.0 as u64).encode(buf); - } - } - - impl Decode for NodeIdx { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - u64::decode(buf).map(|idx| Self(idx as usize)) - } - } - - impl From::Error>> - for GtreeDecodeError - where - T: Decode, - T::Summary: Decode, - { - #[inline] - fn from(err: InodeDecodeError<::Error>) -> Self { - match err { - InodeDecodeError::Bool(err) => Self::Bool(err), - InodeDecodeError::Int(err) => Self::Int(err), - InodeDecodeError::Summary(err) => Self::Summary(err), - } - } - } - - impl From> for GtreeDecodeError - where - T: Decode, - T::Summary: Decode, - { - #[inline] - fn from(err: LeafDecodeError) -> Self { - match err { - LeafDecodeError::Item(err) => Self::Item(err), - LeafDecodeError::Int(err) => Self::Int(err), - } - } - } -} - #[cfg(feature = "serde")] mod serde_impls { use core::marker::PhantomData; diff --git a/src/lamport_clock.rs b/src/lamport_clock.rs index 204adca..5ce4a49 100644 --- a/src/lamport_clock.rs +++ b/src/lamport_clock.rs @@ -99,41 +99,3 @@ impl Ord for LamportTimestamp { self.into_u64().cmp(&other.into_u64()) } } - -#[cfg(feature = "encode")] -mod encode { - use super::*; - use crate::encode::{self, Buffer, Decode, Encode}; - - impl Encode for LamportClock { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.next_timestamp.encode(buf); - } - } - - impl Encode for LamportTimestamp { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.inner.encode(buf); - } - } - - impl Decode for LamportClock { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - u64::decode(buf).map(|next_timestamp| Self { next_timestamp }) - } - } - - impl Decode for LamportTimestamp { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - u64::decode(buf).map(|inner| Self { inner }) - } - } -} diff --git a/src/leb128.rs b/src/leb128.rs deleted file mode 100644 index 8d8bf47..0000000 --- a/src/leb128.rs +++ /dev/null @@ -1,106 +0,0 @@ -use core::fmt; - -macro_rules! encode { - ($fn_name:ident, $ty:ident, $max_encoded_bytes:expr) => { - #[inline] - pub(crate) fn $fn_name(value: $ty) -> ([u8; $max_encoded_bytes], u8) { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - let (long_array, len_u8) = varint_simd::encode(value); - let mut short_array = [0; $max_encoded_bytes]; - let len = len_u8 as usize; - short_array[..len].copy_from_slice(&long_array[..len]); - (short_array, len_u8) - } - #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] - { - let mut buf = [0; $max_encoded_bytes]; - let len = unsigned_varint::encode::$ty(value, &mut buf).len(); - (buf, len as u8) - } - } - }; -} - -macro_rules! decode { - ($fn_name:ident, $ty:ident) => { - #[inline] - pub(crate) fn $fn_name(buf: &[u8]) -> Result<($ty, u8), DecodeError> { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - let (decoded, len) = varint_simd::decode(buf)?; - // TODO: this check shouldn't be necessary, `decode` should - // fail. Open an issue. - if buf.len() < len { - return Err(DecodeError::NotEnoughBytes); - } - Ok((decoded, len as u8)) - } - #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] - { - let (decoded, rest) = unsigned_varint::decode::$ty(buf)?; - Ok((decoded, (buf.len() - rest.len()) as u8)) - } - } - }; -} - -encode!(encode_u16, u16, 3); -encode!(encode_u32, u32, 5); -encode!(encode_u64, u64, 10); - -decode!(decode_u16, u16); -decode!(decode_u32, u32); -decode!(decode_u64, u64); - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub(crate) enum DecodeError { - NotEnoughBytes, - #[cfg_attr( - any(target_arch = "x86", target_arch = "x86_64"), - allow(dead_code) - )] - NotMinimal, - Overflow, -} - -impl fmt::Display for DecodeError { - #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::NotEnoughBytes => f.write_str("not enough input bytes"), - Self::NotMinimal => f.write_str("encoding is not minimal"), - Self::Overflow => f.write_str("input bytes exceed maximum"), - } - } -} - -impl core::error::Error for DecodeError {} - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -impl From for DecodeError { - #[inline] - fn from(err: varint_simd::VarIntDecodeError) -> Self { - match err { - varint_simd::VarIntDecodeError::Overflow => Self::Overflow, - varint_simd::VarIntDecodeError::NotEnoughBytes => { - Self::NotEnoughBytes - }, - } - } -} - -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -impl From for DecodeError { - #[inline] - fn from(err: unsigned_varint::decode::Error) -> Self { - match err { - unsigned_varint::decode::Error::Insufficient => { - Self::NotEnoughBytes - }, - unsigned_varint::decode::Error::Overflow => Self::Overflow, - unsigned_varint::decode::Error::NotMinimal => Self::NotMinimal, - _ => unimplemented!(), - } - } -} diff --git a/src/lib.rs b/src/lib.rs index cb7334d..8b016ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,14 +7,9 @@ extern crate alloc; #[doc(hidden)] pub mod debug; pub mod diff; -#[cfg(feature = "encode")] -#[cfg_attr(docsrs, doc(cfg(feature = "encode")))] -pub mod encode; mod forest; mod gtree; mod lamport_clock; -#[cfg(feature = "encode")] -mod leb128; pub mod node; mod node_id; mod op_log; diff --git a/src/node_id.rs b/src/node_id.rs index 2132ae5..2b15e97 100644 --- a/src/node_id.rs +++ b/src/node_id.rs @@ -75,42 +75,3 @@ impl fmt::Debug for LocalNodeId { f.write_str("LocalNodeId(..)") } } - -#[cfg(feature = "encode")] -mod encode { - use super::*; - use crate::encode::{self, Buffer, Decode, Encode}; - - impl Encode for GlobalNodeId { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.creation_timestamp.encode(buf); - } - } - - impl Decode for GlobalNodeId { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - OpTimestamp::decode(buf) - .map(|creation_timestamp| Self { creation_timestamp }) - } - } - - impl Encode for LocalNodeId { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.forest_key.encode(buf); - } - } - - impl Decode for LocalNodeId { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - forest::NodeKey::decode(buf).map(|forest_key| Self { forest_key }) - } - } -} diff --git a/src/op_log.rs b/src/op_log.rs index bf8a286..ad0e36f 100644 --- a/src/op_log.rs +++ b/src/op_log.rs @@ -184,7 +184,7 @@ impl OpLog { } /// TODO: docs. - #[cfg_attr(not(feature = "encode"), allow(dead_code))] + #[cfg_attr(not(feature = "serde"), allow(dead_code))] #[inline] pub(crate) fn reconstruct_forest(&mut self) -> Forest { let mut iter = self.gtree.iter_forward_mut(); @@ -415,137 +415,6 @@ impl gtree::Summarize for LogEntry { } } -#[cfg(feature = "encode")] -pub(crate) mod encode { - use super::*; - use crate::encode::{self, Buffer, Decode, Encode}; - - pub(crate) enum OpLogDecodeError { - #[allow(dead_code)] - Bool(encode::BoolDecodeError), - #[allow(dead_code)] - Int(encode::IntDecodeError), - Metadata(M), - } - - impl Encode for OpLog { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.gtree.encode(buf); - } - } - - impl Decode for OpLog { - type Error = OpLogDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - Gtree::decode(buf) - .map_err(|err| match err { - gtree::GtreeDecodeError::Bool(err) => { - OpLogDecodeError::Bool(err) - }, - gtree::GtreeDecodeError::Int(err) => { - OpLogDecodeError::Int(err) - }, - gtree::GtreeDecodeError::Item(err) => err, - gtree::GtreeDecodeError::Summary(err) => { - OpLogDecodeError::Int(err) - }, - }) - .map(|gtree| Self { gtree }) - } - } - - impl Encode for Op { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.new_parent.encode(buf); - self.node_id.encode(buf); - self.timestamp.encode(buf); - if let Some(metadata) = self.metadata() { - metadata.encode(buf); - } - } - } - - impl Decode for Op { - type Error = OpLogDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let new_parent = - GlobalNodeId::decode(buf).map_err(OpLogDecodeError::Int)?; - - let node_id = - GlobalNodeId::decode(buf).map_err(OpLogDecodeError::Int)?; - - let timestamp = - OpTimestamp::decode(buf).map_err(OpLogDecodeError::Int)?; - - let is_creation = node_id.creation_timestamp == timestamp; - - let metadata = if is_creation { - M::decode(buf) - .map(MaybeUninit::new) - .map_err(OpLogDecodeError::Metadata)? - } else { - MaybeUninit::uninit() - }; - - Ok(Self { metadata, new_parent, node_id, timestamp }) - } - } - - impl Encode for OpKey { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.0.encode(buf); - } - } - - impl Decode for OpKey { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - gtree::Key::decode(buf).map(Self) - } - } - - impl Encode for LogEntry { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.prev_parent.encode(buf); - self.op.encode(buf); - } - } - - impl Decode for LogEntry { - type Error = OpLogDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let prev_parent = - PrevParent::decode(buf).map_err(OpLogDecodeError::Int)?; - - let op = Op::::decode(buf)?; - - Ok(Self { prev_parent, op }) - } - } - - impl From> for encode::DecodeError { - #[inline] - fn from(err: OpLogDecodeError) -> Self { - match err { - OpLogDecodeError::Metadata(err) => Self::Metadata(err), - _ => Self::InvalidData, - } - } - } -} - #[cfg(feature = "serde")] pub(crate) mod serde_impls { use core::marker::PhantomData; diff --git a/src/op_timestamp.rs b/src/op_timestamp.rs index 7a37667..359aab9 100644 --- a/src/op_timestamp.rs +++ b/src/op_timestamp.rs @@ -95,31 +95,6 @@ impl fmt::Display for OpTimestampFromStrError { } } -#[cfg(feature = "encode")] -mod encode { - use super::*; - use crate::encode::{self, Buffer, Decode, Encode}; - - impl Encode for OpTimestamp { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.created_by.encode(buf); - self.lamport_timestamp.encode(buf); - } - } - - impl Decode for OpTimestamp { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - let created_by = PeerId::decode(buf)?; - let lamport_timestamp = LamportTimestamp::decode(buf)?; - Ok(Self { created_by, lamport_timestamp }) - } - } -} - #[cfg(feature = "serde")] mod serde_impls { use serde::de; diff --git a/src/ops.rs b/src/ops.rs index 313e729..2231343 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -6,6 +6,7 @@ pub use crate::op_timestamp::OpTimestamp; /// TODO: docs. #[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Creation { pub(crate) node_id: GlobalNodeId, pub(crate) parent_id: GlobalNodeId, @@ -14,6 +15,7 @@ pub struct Creation { /// TODO: docs. #[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Deletion { pub(crate) node_id: GlobalNodeId, pub(crate) timestamp: OpTimestamp, @@ -21,6 +23,7 @@ pub struct Deletion { /// TODO: docs. #[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Move { pub(crate) node_id: GlobalNodeId, pub(crate) parent_id: GlobalNodeId, @@ -120,157 +123,3 @@ impl Move { self.timestamp } } - -#[cfg(feature = "encode")] -mod encode { - use super::*; - use crate::encode::{self, Buffer, CreationDecodeError, Decode, Encode}; - - impl Encode for Creation { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.node_id.encode(buf); - self.parent_id.encode(buf); - self.metadata.encode(buf); - } - } - - impl Decode for Creation { - type Error = CreationDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - Ok(Self { - node_id: GlobalNodeId::decode(buf) - .map_err(CreationDecodeError::Int)?, - parent_id: GlobalNodeId::decode(buf) - .map_err(CreationDecodeError::Int)?, - metadata: M::decode(buf) - .map_err(CreationDecodeError::Metadata)?, - }) - } - } - - impl Encode for Deletion { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.node_id.encode(buf); - self.timestamp.encode(buf); - } - } - - impl Decode for Deletion { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - Ok(Self { - node_id: GlobalNodeId::decode(buf)?, - timestamp: OpTimestamp::decode(buf)?, - }) - } - } - - impl Encode for Move { - #[inline] - fn encode(&self, buf: &mut impl Buffer) { - self.node_id.encode(buf); - self.parent_id.encode(buf); - self.timestamp.encode(buf); - } - } - - impl Decode for Move { - type Error = encode::IntDecodeError; - - #[inline] - fn decode(buf: &mut &[u8]) -> Result { - Ok(Self { - node_id: GlobalNodeId::decode(buf)?, - parent_id: GlobalNodeId::decode(buf)?, - timestamp: OpTimestamp::decode(buf)?, - }) - } - } - - #[cfg(feature = "serde")] - mod serde { - use core::fmt; - - use ::serde::{de, ser}; - - use super::*; - - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl ser::Serialize for Creation { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: ser::Serializer, - { - encode::SerdeCompat(self).serialize(serializer) - } - } - - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl<'de, M> de::Deserialize<'de> for Creation - where - M: Decode, - { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - encode::SerdeCompat::deserialize(deserializer) - .map(|encode::SerdeCompat(this)| this) - } - } - - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl ser::Serialize for Deletion { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: ser::Serializer, - { - encode::SerdeCompat(self).serialize(serializer) - } - } - - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl<'de> de::Deserialize<'de> for Deletion { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - encode::SerdeCompat::deserialize(deserializer) - .map(|encode::SerdeCompat(this)| this) - } - } - - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl ser::Serialize for Move { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: ser::Serializer, - { - encode::SerdeCompat(self).serialize(serializer) - } - } - - #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] - impl<'de> de::Deserialize<'de> for Move { - #[inline] - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - encode::SerdeCompat::deserialize(deserializer) - .map(|encode::SerdeCompat(this)| this) - } - } - } -} diff --git a/src/tree.rs b/src/tree.rs index de3260a..8de6304 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -2,8 +2,6 @@ use core::fmt; use core::marker::PhantomData; use crate::diff::TreeDiff; -#[cfg(feature = "encode")] -use crate::encode::{Buffer, Decode, DecodeError, Encode}; use crate::forest::{Forest, NodeState}; use crate::lamport_clock::LamportClock; use crate::node::{self, IsVisible, Node, NodeMut, Visible}; @@ -31,44 +29,6 @@ pub struct Tree { } impl Tree { - /// TODO: docs. - #[cfg(feature = "encode")] - #[cfg_attr(docsrs, doc(cfg(feature = "encode")))] - #[inline] - pub fn decode( - buf: &mut &[u8], - peer_id: PeerId, - ) -> Result> - where - M: Decode, - { - let protocol_version = crate::ProtocolVersion::decode(buf) - .map_err(|_| DecodeError::InvalidData)?; - - if protocol_version != crate::PROTOCOL_VERSION { - return Err(DecodeError::ProtocolMismatch { - encoded_on: protocol_version, - decoding_on: crate::PROTOCOL_VERSION, - }); - } - - let lamport_clock = - LamportClock::decode(buf).map_err(|_| DecodeError::InvalidData)?; - - let mut op_log = OpLog::::decode(buf)?; - - let has_encoded_tree_state = - bool::decode(buf).map_err(|_| DecodeError::InvalidData)?; - - let forest = if has_encoded_tree_state { - Forest::decode(buf).map_err(|_| DecodeError::InvalidData)? - } else { - op_log.reconstruct_forest() - }; - - Ok(Self { lamport_clock, op_log, peer_id, forest }) - } - /// TODO: docs. #[cfg(feature = "serde")] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] @@ -77,38 +37,6 @@ impl Tree { DeserializeTree::new(peer_id) } - /// TODO: docs. - #[cfg(feature = "encode")] - #[cfg_attr(docsrs, doc(cfg(feature = "encode")))] - #[inline] - pub fn encode(&self) -> Vec - where - M: Encode, - { - let mut buf = Vec::new(); - self.encode_into::(&mut buf); - buf - } - - /// TODO: docs. - #[cfg(feature = "encode")] - #[cfg_attr(docsrs, doc(cfg(feature = "encode")))] - #[inline] - pub fn encode_into( - &self, - buf: &mut impl Buffer, - ) where - M: Encode, - { - crate::PROTOCOL_VERSION.encode(buf); - self.lamport_clock.encode(buf); - self.op_log.encode(buf); - ENCODE_TREE_STATE.encode(buf); - if ENCODE_TREE_STATE { - self.forest.encode(buf); - } - } - /// TODO: docs. #[track_caller] #[inline] diff --git a/tests/common/tree.rs b/tests/common/tree.rs index 879adb2..ddf4559 100644 --- a/tests/common/tree.rs +++ b/tests/common/tree.rs @@ -2,7 +2,7 @@ use core::borrow::Borrow; use core::fmt; use core::ops::{Deref, DerefMut}; -use pando::encode::{Decode, DecodeError}; +use pando::PeerId; use pando::node::{ IsVisible, LocalNodeId, @@ -12,7 +12,6 @@ use pando::node::{ NodeState, }; use pando::ops::{Creation, Deletion, Move}; -use pando::{PeerId, encode}; use rand::distr::{self, Distribution}; use super::{Op, OpKind}; @@ -70,21 +69,6 @@ impl Tree { self.create_node_inner(parent_id, metadata) } - pub(crate) fn decode( - encoded: impl AsRef<[u8]>, - peer_id: PeerId, - ) -> Result> - where - T: Decode, - { - let mut this = Self { - inner: pando::Tree::decode(&mut encoded.as_ref(), peer_id)?, - node_ids: NodeIds::default(), - }; - this.recompute_ids(); - Ok(this) - } - /// Deletes the node at the given path. #[track_caller] pub(crate) fn delete_node_at( diff --git a/tests/encode.rs b/tests/encode.rs deleted file mode 100644 index ebf55f8..0000000 --- a/tests/encode.rs +++ /dev/null @@ -1,88 +0,0 @@ -#![allow(missing_docs)] - -mod common; - -use common::{OpKind, Tree}; - -#[test] -fn encode_fuzz_4_ops_state() { - fuzz(FuzzOpts { num_ops: 4, ..Default::default() }) -} - -#[test] -fn encode_fuzz_4_ops_no_state() { - fuzz(FuzzOpts { encode_state: false, num_ops: 4, ..Default::default() }) -} - -#[test] -fn encode_fuzz_32_ops_state() { - fuzz(FuzzOpts { num_ops: 32, ..Default::default() }) -} - -#[test] -fn encode_fuzz_32_ops_no_state() { - fuzz(FuzzOpts { encode_state: false, num_ops: 32, ..Default::default() }) -} - -#[test] -fn encode_fuzz_256_ops_state() { - fuzz(FuzzOpts { num_ops: 256, ..Default::default() }) -} - -#[test] -fn encode_fuzz_256_ops_no_state() { - fuzz(FuzzOpts { encode_state: false, num_ops: 256, ..Default::default() }) -} - -#[test] -fn encode_fuzz_2048_ops_state() { - fuzz(FuzzOpts { num_ops: 2048, ..Default::default() }) -} - -#[test] -fn encode_fuzz_2048_ops_no_state() { - fuzz(FuzzOpts { encode_state: false, num_ops: 2048, ..Default::default() }) -} - -#[derive(Debug)] -#[non_exhaustive] -struct FuzzOpts { - encode_state: bool, - num_ops: u32, -} - -impl Default for FuzzOpts { - fn default() -> Self { - Self { encode_state: true, num_ops: 1 } - } -} - -#[track_caller] -fn fuzz(opts: FuzzOpts) { - assert!(opts.num_ops > 0); - - let mut tree = Tree::new(42u32, 1); - - let weights = - [(OpKind::Creation, 50), (OpKind::Deletion, 10), (OpKind::Move, 40)]; - - common::with_rng(|rng| { - // Perform a bunch of random ops. - for _ in 0..opts.num_ops { - tree.perform_random_op(weights, |_| 42, rng); - } - - // Encode the tree. - let encoded = if opts.encode_state { - tree.encode::() - } else { - tree.encode::() - }; - - // Decode the tree. - let decoded = Tree::decode(encoded, 2).expect("failed to decode tree"); - - // Assert that the decoded tree is equal to the original tree. - assert_eq!(tree, decoded); - }); -}