// ... PRIMITIVE TYPES ... use alloc::{string::String, vec::Vec, fmt}; use crate::utils::*; use crate::uuid::UUID4; use crate::*; pub use super::chat::*; #[cfg(all(test, feature = "std"))] use crate::protocol::TestRandom; use crate::byte_order::{ProtoByteOrder, ByteOrder}; // bool impl Serialize for bool { fn mc_serialize(&self, to: &mut S) -> SerializeResult { to.serialize_byte(if *self { 1 } else { 0 }) } } impl Deserialize for bool { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { ProtoByteOrder::read_ubyte(data)?.try_map(move |b| match b { 0x00 => Ok(false), 0x01 => Ok(true), other => Err(DeserializeErr::InvalidBool(other)), }) } } #[cfg(all(test, feature = "std"))] impl TestRandom for bool { fn test_gen_random() -> Self { rand::random() } } macro_rules! def_primitive { ($nam: ty, $read: ident, $write: ident) => { impl Serialize for $nam { fn mc_serialize(&self, to: &mut S) -> SerializeResult { let data = ProtoByteOrder::$write(*self); to.serialize_bytes(&data) } } impl Deserialize for $nam { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { ProtoByteOrder::$read(data) } } #[cfg(all(test, feature = "std"))] impl TestRandom for $nam { fn test_gen_random() -> Self { rand::random() } } }; } def_primitive!(u8, read_ubyte, write_ubyte); def_primitive!(i8, read_byte, write_byte); def_primitive!(u16, read_ushort, write_ushort); def_primitive!(i16, read_short, write_short); def_primitive!(u32, read_uint, write_uint); def_primitive!(i32, read_int, write_int); def_primitive!(u64, read_ulong, write_ulong); def_primitive!(i64, read_long, write_long); def_primitive!(u128, read_u2long, write_u2long); def_primitive!(i128, read_2long, write_2long); def_primitive!(f32, read_float, write_float); def_primitive!(f64, read_double, write_double); // VAR INT AND VAR LONG macro_rules! def_varnum { ($nam: ident, $data_type: ty, $working_type: ty, $max_bytes: literal) => { #[derive(Copy, Clone, PartialOrd, PartialEq, Default, Hash, Ord, Eq)] pub struct $nam(pub $data_type); impl Serialize for $nam { fn mc_serialize(&self, to: &mut S) -> SerializeResult { let mut out = [0u8; $max_bytes]; let mut v: $working_type = self.0 as $working_type; let mut byte_idx = 0; let mut has_more = true; while has_more { if byte_idx == out.len() { panic!("tried to write too much data for {}", stringify!($nam)); } let mut v_byte = (v & 0x7F) as u8; v >>= 7; has_more = v != 0; if has_more { v_byte |= 0x80; } out[byte_idx] = v_byte; byte_idx += 1; } to.serialize_bytes(&out[..byte_idx]) } } impl Deserialize for $nam { fn mc_deserialize(orig_data: &[u8]) -> DeserializeResult { let mut data = orig_data; let mut v: $working_type = 0; let mut bit_place: usize = 0; let mut i: usize = 0; let mut has_more = true; while has_more { if i == $max_bytes { return DeserializeErr::VarNumTooLong(Vec::from(&orig_data[..i])).into(); } let Deserialized { value: byte, data: rest } = ProtoByteOrder::read_ubyte(data)?; data = rest; has_more = byte & 0x80 != 0; v |= ((byte as $working_type) & 0x7F) << bit_place; bit_place += 7; i += 1; } Deserialized::ok(Self(v as $data_type), data) } } impl From<$data_type> for $nam { fn from(other: $data_type) -> Self { Self(other) } } impl From<$nam> for $data_type { fn from(other: $nam) -> Self { other.0 } } impl core::ops::Deref for $nam { type Target = $data_type; fn deref(&self) -> &Self::Target { &self.0 } } impl fmt::Display for $nam { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } impl fmt::Debug for $nam { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(stringify!($nam))?; f.write_str("(")?; write!(f, "{}", self.0)?; f.write_str(")")?; Ok(()) } } #[cfg(all(test, feature = "std"))] impl TestRandom for $nam { fn test_gen_random() -> Self { let out: $data_type = rand::random(); Self(out) } } } } def_varnum!(VarInt, i32, u32, 5); def_varnum!(VarLong, i64, u64, 10); // STRING impl Serialize for String { fn mc_serialize(&self, to: &mut S) -> SerializeResult { to.serialize_other(&VarInt(self.len() as i32))?; to.serialize_bytes(self.as_bytes()) } } impl Deserialize for String { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { VarInt::mc_deserialize(data)?.and_then(move |length, rest| { if length.0 < 0 { Err(DeserializeErr::NegativeLength(length)) } else { take(length.0 as usize, rest)?.try_map(move |taken| { String::from_utf8(taken.to_vec()).map_err(DeserializeErr::BadStringEncoding) }) } }) } } #[cfg(all(test, feature = "std"))] impl TestRandom for String { fn test_gen_random() -> Self { let raw_len: u8 = rand::random(); let len = raw_len as usize; let mut out = String::with_capacity(len); for _ in 0..len { let c_idx: u8 = rand::random::() % 36; let c = if c_idx <= 10 { (48 + c_idx) as char } else { ((c_idx - 10) + 65) as char }; out.push(c) } out } } // position #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub struct IntPosition { pub x: i32, pub y: i16, pub z: i32, } impl Serialize for IntPosition { fn mc_serialize(&self, to: &mut S) -> SerializeResult { let x_raw = if self.x < 0 { (self.x + 0x2000000) as u64 | 0x2000000 } else { self.x as u64 } & 0x3FFFFFF; let z_raw = if self.z < 0 { (self.z + 0x2000000) as u64 | 0x2000000 } else { self.z as u64 } & 0x3FFFFFF; let y_raw = if self.y < 0 { (self.y + 0x800) as u64 | 0x800 } else { self.y as u64 } & 0xFFF; let data = ProtoByteOrder::write_ulong(((x_raw << 38) | (z_raw << 12) | y_raw) as u64); to.serialize_bytes(&data) } } impl Deserialize for IntPosition { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { let Deserialized { value: raw, data } = ProtoByteOrder::read_ulong(data)?; let mut x = ((raw >> 38) as u32) & 0x3FFFFFF; let mut z = ((raw >> 12) & 0x3FFFFFF) as u32; let mut y = ((raw & 0xFFF) as u16) & 0xFFF; if (x & 0x2000000) != 0 { // is the 26th bit set // if so, treat the rest as a positive integer, and treat 26th bit as -2^25 // 2^25 == 0x2000000 // 0x1FFFFFF == 2^26 - 1 (all places set to 1 except 26th place) x = (((x & 0x1FFFFFF) as i32) - 0x2000000) as u32; } if (y & 0x800) != 0 { y = (((y & 0x7FF) as i16) - 0x800) as u16; } if (z & 0x2000000) != 0 { z = (((z & 0x1FFFFFF) as i32) - 0x2000000) as u32; } Deserialized::ok( IntPosition { x: x as i32, y: y as i16, z: z as i32, }, data, ) } } #[cfg(all(test, feature = "std"))] impl TestRandom for IntPosition { fn test_gen_random() -> Self { let x: i32 = ((rand::random::() % (1 << 26)) as i32) - (1 << 25); let z: i32 = ((rand::random::() % (1 << 26)) as i32) - (1 << 25); let y: i16 = ((rand::random::() % (1 << 12)) as i16) - (1 << 11); Self { x, y, z } } } // angle #[derive(Copy, Clone, PartialEq, Hash, Debug)] pub struct Angle { pub value: u8, } impl Serialize for Angle { fn mc_serialize(&self, to: &mut S) -> SerializeResult { to.serialize_byte(self.value) } } impl Deserialize for Angle { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { Ok(ProtoByteOrder::read_ubyte(data)?.map(move |b| Angle { value: b })) } } #[cfg(all(test, feature = "std"))] impl TestRandom for Angle { fn test_gen_random() -> Self { Self { value: rand::random(), } } } // UUID impl Serialize for UUID4 { fn mc_serialize(&self, to: &mut S) -> SerializeResult { let bytes = ProtoByteOrder::write_u2long(self.to_u128()); to.serialize_bytes(&bytes[..]) } } impl Deserialize for UUID4 { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { Ok(ProtoByteOrder::read_u2long(data)?.map(move |raw| UUID4::from(raw))) } } #[cfg(all(test, feature = "std"))] impl TestRandom for UUID4 { fn test_gen_random() -> Self { UUID4::random() } } // NBT #[derive(Clone, PartialEq, Debug)] pub struct NamedNbtTag { pub root: nbt::NamedTag, } impl Serialize for NamedNbtTag { fn mc_serialize(&self, to: &mut S) -> SerializeResult { let bytes = self.root.bytes(); to.serialize_bytes(bytes.as_slice()) } } impl Deserialize for NamedNbtTag { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { Ok( nbt::NamedTag::root_compound_tag_from_bytes(data)? .map(move |root| NamedNbtTag { root }), ) } } impl From for NamedNbtTag { fn from(root: nbt::NamedTag) -> Self { Self { root } } } impl Into for NamedNbtTag { fn into(self) -> nbt::NamedTag { self.root } } #[cfg(all(test, feature = "std"))] impl TestRandom for NamedNbtTag { fn test_gen_random() -> Self { Self { root: nbt::NamedTag::test_gen_random(), } } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct FixedInt { raw: i32, } impl Serialize for FixedInt { fn mc_serialize(&self, to: &mut S) -> SerializeResult { to.serialize_other(&self.raw) } } impl Deserialize for FixedInt { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { Ok(i32::mc_deserialize(data)?.map(move |raw| FixedInt { raw })) } } impl FixedInt { pub fn new(data: f64, fractional_bytes: usize) -> Self { Self { raw: (data * ((1 << fractional_bytes) as f64)) as i32, } } pub fn into_float(self, fractional_bytes: usize) -> f64 { (self.raw as f64) / ((1 << fractional_bytes) as f64) } } #[cfg(all(test, feature = "std"))] impl TestRandom for FixedInt { fn test_gen_random() -> Self { FixedInt::new(f64::test_gen_random(), 16) } } #[derive(Default)] pub struct BytesSerializer { data: Vec, } impl Serializer for BytesSerializer { fn serialize_bytes(&mut self, data: &[u8]) -> SerializeResult { self.data.extend_from_slice(data); Ok(()) } } impl BytesSerializer { pub fn with_capacity(cap: usize) -> Self { BytesSerializer { data: Vec::with_capacity(cap), } } pub fn into_bytes(self) -> Vec { self.data } } impl Serialize for Option where T: Serialize, { fn mc_serialize(&self, to: &mut S) -> SerializeResult { match self { Some(value) => { to.serialize_other(&true)?; to.serialize_other(value) } None => to.serialize_other(&false), } } } impl Deserialize for Option where T: Deserialize, { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { bool::mc_deserialize(data)?.and_then(move |is_present, data| { if is_present { Ok(T::mc_deserialize(data)?.map(move |component| Some(component))) } else { Deserialized::ok(None, data) } }) } } #[cfg(all(test, feature = "std"))] impl TestRandom for Option where T: TestRandom, { fn test_gen_random() -> Self { let is_present: bool = rand::random(); if is_present { Some(T::test_gen_random()) } else { None } } } // SLOT #[derive(Debug, PartialEq, Clone)] pub struct ItemStack { pub item_id: VarInt, pub item_count: i8, pub nbt: Option, } impl Serialize for ItemStack { fn mc_serialize(&self, to: &mut S) -> SerializeResult { to.serialize_other(&self.item_id)?; to.serialize_other(&self.item_count)?; match self.nbt.as_ref() { Some(nbt) => to.serialize_bytes(nbt.bytes().as_slice()), None => to.serialize_byte(nbt::Tag::End.id()), } } } impl Deserialize for ItemStack { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { let Deserialized { value: item_id, data } = VarInt::mc_deserialize(data)?; let Deserialized { value: item_count, data } = i8::mc_deserialize(data)?; if data.is_empty() { return Err(DeserializeErr::Eof); } let id = data[0]; let rest = &data[1..]; Ok(match id { 0x00 => Deserialized { value: None, data: rest, }, _ => nbt::read_named_tag(data)?.map(move |tag| Some(tag)), }.map(move |nbt| Self { item_id, item_count, nbt, })) } } #[cfg(all(test, feature = "std"))] impl TestRandom for ItemStack { fn test_gen_random() -> Self { let item_id = VarInt::test_gen_random(); let item_count = i8::test_gen_random() % 65; let nbt = >::test_gen_random(); Self { item_id, item_count, nbt, } } } pub type Slot = Option; macro_rules! def_vector_type { ($name: ident, $($fnam: ident),+) => { crate::as_item! { pub struct $name { $(pub $fnam: T),+ } } impl Serialize for $name where T: Serialize { fn mc_serialize(&self, to: &mut S) -> SerializeResult { $( to.serialize_other(&self.$fnam)?; )+ Ok(()) } } impl Deserialize for $name where T: Deserialize { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { $(let Deserialized { value: $fnam, data } = T::mc_deserialize(data)?;)+ Deserialized::ok(Self { $($fnam),+ }, data) } } #[cfg(all(test, feature = "std"))] impl TestRandom for $name where T: TestRandom { fn test_gen_random() -> Self { Self { $($fnam: T::test_gen_random(),)+ } } } impl Clone for $name where T: Clone { fn clone(&self) -> Self { Self { $($fnam: self.$fnam.clone(),)+ } } } impl Copy for $name where T: Copy {} impl PartialEq<$name> for $name where T: PartialEq { fn eq(&self, other: &$name) -> bool { $(self.$fnam.eq(&other.$fnam)) && + } fn ne(&self, other: &$name) -> bool { $(self.$fnam.ne(&other.$fnam)) || + } } impl core::hash::Hash for $name where T: core::hash::Hash { fn hash(&self, state: &mut H) { $(self.$fnam.hash(state);)+ } } impl fmt::Debug for $name where T: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(stringify!($name))?; f.write_str("( ")?; $( f.write_str(stringify!($fnam))?; f.write_str("=")?; self.$fnam.fmt(f)?; f.write_str(" ")?; )+ f.write_str(")")?; Ok(()) } } impl fmt::Display for $name where T: fmt::Display { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(stringify!($name))?; f.write_str("( ")?; $( f.write_str(stringify!($fnam))?; f.write_str("=")?; self.$fnam.fmt(f)?; f.write_str(" ")?; )+ f.write_str(")")?; Ok(()) } } impl From<$name> for ($(crate::instead_of_ident!($fnam, T)),+) { fn from(other: $name) -> Self { ($(other.$fnam),+) } } impl<'a, T> From<&'a $name> for ($(&'a crate::instead_of_ident!($fnam, T)),+) { fn from(other: &'a $name) -> Self { ($(&other.$fnam),+) } } impl<'a, T> From<&'a $name> for ($(crate::instead_of_ident!($fnam, T)),+) where T: Clone { fn from(other: &'a $name) -> Self { ($(other.$fnam.clone()),+) } } impl From<($(crate::instead_of_ident!($fnam, T)),+)> for $name { fn from(other: ($(crate::instead_of_ident!($fnam, T)),+)) -> Self { let ($($fnam),+) = other; Self { $($fnam),+ } } } impl<'a, T> From<&'a ($(crate::instead_of_ident!($fnam, T)),+)> for $name where T: Clone { fn from(other: &'a ($(crate::instead_of_ident!($fnam, T)),+)) -> Self { let ($($fnam),+) = other; $(let $fnam = $fnam.clone();)+ Self { $($fnam),+ } } } impl<'a, T> From<($(&'a crate::instead_of_ident!($fnam, T)),+)> for $name where T: Clone { fn from(other: ($(&'a crate::instead_of_ident!($fnam, T)),+)) -> Self { let ($($fnam),+) = other; $(let $fnam = $fnam.clone();)+ Self { $($fnam),+ } } } impl $name { pub fn from_other(other: O) -> Self where O: Into<($(crate::instead_of_ident!($fnam, T)),+)> { let ($($fnam),+) = other.into(); Self { $($fnam,)+ } } pub fn as_other(&self) -> O where O: From<($(crate::instead_of_ident!($fnam, T)),+)>, T: Clone { O::from(self.into()) } pub fn into_other(self) -> O where O: From<($(crate::instead_of_ident!($fnam, T)),+)> { O::from(self.into()) } } }; } def_vector_type!(Vec3, x, y, z); def_vector_type!(Vec2, x, y); def_vector_type!(ChunkPosition, x, z); pub type TopDownPosition = ChunkPosition; def_vector_type!(EntityRotation, yaw, pitch); proto_struct!(EntityLocation { position: Vec3

, rotation: EntityRotation }); #[derive(Clone, Debug, PartialEq)] pub struct CountedArray { data: Vec, _counter_type: core::marker::PhantomData, } pub trait ArrayCounter: Serialize + Deserialize { fn as_count(&self) -> usize; fn from_count(count: usize) -> Self; } impl Serialize for CountedArray where E: Serialize, C: ArrayCounter { fn mc_serialize(&self, to: &mut S) -> SerializeResult { let count = C::from_count(self.data.len()); to.serialize_other(&count)?; for elem in &self.data { to.serialize_other(elem)?; } Ok(()) } } impl Deserialize for CountedArray where E: Deserialize, C: ArrayCounter { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { let Deserialized { value: count, mut data } = C::mc_deserialize(data)?; let count = count.as_count(); let mut elems = Vec::with_capacity(count); for _ in 0..count { let Deserialized { value: elem, data: rest } = E::mc_deserialize(data)?; data = rest; elems.push(elem); } Deserialized::ok(Self { data: elems, _counter_type: core::marker::PhantomData, }, data) } } impl core::ops::Deref for CountedArray where C: ArrayCounter { type Target = Vec; fn deref(&self) -> &Self::Target { &self.data } } impl core::ops::DerefMut for CountedArray where C: ArrayCounter { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data } } impl From> for Vec where C: ArrayCounter { fn from(other: CountedArray) -> Self { other.data } } impl From> for CountedArray where C: ArrayCounter { fn from(data: Vec) -> Self { Self { data, _counter_type: core::marker::PhantomData, } } } #[cfg(all(test, feature = "std"))] impl TestRandom for CountedArray where E: TestRandom, C: ArrayCounter { fn test_gen_random() -> Self { let elem_count: usize = rand::random::() % 32; let mut out = Vec::with_capacity(elem_count); for _ in 0..elem_count { out.push(E::test_gen_random()); } out.into() } } impl ArrayCounter for VarInt { fn as_count(&self) -> usize { self.0 as usize } fn from_count(count: usize) -> Self { Self(count as i32) } } impl ArrayCounter for i16 { fn as_count(&self) -> usize { (*self) as usize } fn from_count(count: usize) -> Self { count as i16 } } impl ArrayCounter for i32 { fn as_count(&self) -> usize { (*self) as usize } fn from_count(count: usize) -> Self { count as i32 } } impl ArrayCounter for i8 { fn as_count(&self) -> usize { (*self) as usize } fn from_count(count: usize) -> Self { count as i8 } } #[derive(Debug, Clone, PartialEq)] pub struct RemainingBytes { pub data: Vec, } impl Serialize for RemainingBytes { fn mc_serialize(&self, to: &mut S) -> SerializeResult { to.serialize_bytes(self.data.as_slice()) } } impl Deserialize for RemainingBytes { fn mc_deserialize(data: &[u8]) -> DeserializeResult<'_, Self> { Deserialized::ok( RemainingBytes { data: Vec::from(data), }, &[], ) } } impl Into> for RemainingBytes { fn into(self) -> Vec { self.data } } impl From> for RemainingBytes { fn from(data: Vec) -> Self { Self { data } } } impl core::ops::Deref for RemainingBytes { type Target = Vec; fn deref(&self) -> &Self::Target { &self.data } } impl core::ops::DerefMut for RemainingBytes { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data } } #[cfg(all(test, feature = "std"))] impl TestRandom for RemainingBytes { fn test_gen_random() -> Self { let size: usize = rand::random::() % 256; let mut out = Vec::with_capacity(size); for _ in 0..size { out.push(rand::random()); } Self { data: out } } } #[cfg(test)] mod tests { use super::*; use alloc::fmt::Debug; use alloc::borrow::ToOwned; #[test] fn test_bool() { test_type(true); test_type(false); } #[test] fn test_signed_byte() { test_type(0i8); test_type(127i8); test_type(-15i8); } #[test] fn test_unsigned_byte() { test_type(0u8); test_type(128u8); test_type(255u8); } #[test] fn test_signed_short() { test_type(0i16); test_type(-88i16); test_type(25521i16); } #[test] fn test_unsigned_short() { test_type(0u16); test_type(1723u16); test_type(65534u16); } #[test] fn test_signed_int() { test_type(0i32); test_type(123127i32); test_type(-171238i32); test_type(2147483647i32); } #[test] fn test_signed_long() { test_type(0i64); test_type(123127i64); test_type(-12123127i64); test_type(2147483647i64); test_type(-10170482028482i64); } #[test] fn test_float() { test_type(0.2313f32); test_type(0f32); test_type(123123213f32); test_type(-123123f32); } #[test] fn test_double() { test_type(0.2313f64); test_type(0f64); test_type(123123213f64); test_type(-123123f64); } #[test] fn test_var_int() { test_type(VarInt(0)); test_type(VarInt(1231231)); test_type(VarInt(2147483647)); test_type(VarInt(-2147483648)); test_type(VarInt(-1)); test_type(VarInt(-1001237)); } #[test] fn test_var_long() { test_type(VarLong(0)); test_type(VarLong(1231231)); test_type(VarLong(12312319123)); test_type(VarLong(9223372036854775807)); test_type(VarLong(-1)); test_type(VarLong(-12312319123)); test_type(VarLong(-9223372036854775808)); test_type(VarLong(-1001237)); } #[test] fn test_string() { test_type(String::from("hello my name is joey 123")); test_type(String::from("")); test_type(String::from("AAAA")); test_type(String::from("hello my name is joey 123").repeat(1000)); } #[test] fn test_nbt() { test_type(NamedNbtTag { root: nbt::Tag::Compound(alloc::vec![ nbt::Tag::String("test 123".to_owned()).with_name("abc 123") ]) .with_name("root"), }) } #[test] fn test_int_position() { test_type(IntPosition { x: 12312, y: -32, z: 321312, }); test_type(IntPosition { x: 12312, y: -32, z: -321312, }); test_type(IntPosition { x: -12312, y: -32, z: -321312, }); test_type(IntPosition { x: -12312, y: 32, z: 321312, }); test_type(IntPosition { x: 0, y: 0, z: 0 }); test_type(IntPosition { x: 48, y: 232, z: 12, }); test_type(IntPosition { x: 33554431, y: 2047, z: 33554431, }); test_type(IntPosition { x: -33554432, y: -2048, z: -33554432, }); test_type(IntPosition { x: 3, y: 0, z: 110655, }); } #[cfg(feature = "std")] #[test] fn test_uuid() { for _ in 0..5 { test_type(UUID4::random()); } } #[test] fn test_angle() { test_type(Angle { value: 0 }); test_type(Angle { value: 24 }); test_type(Angle { value: 255 }); test_type(Angle { value: 8 }); } fn test_type(value: S) { let bytes = { let mut test = BytesSerializer::default(); value .mc_serialize(&mut test) .expect("serialization should succeed"); test.into_bytes() }; let deserialized = S::mc_deserialize(bytes.as_slice()).expect("deserialization should succeed"); assert!(deserialized.data.is_empty()); assert_eq!( deserialized.value, value, "deserialized value == serialized value" ); let re_serialized = { let mut test = BytesSerializer::default(); deserialized .value .mc_serialize(&mut test) .expect("serialization should succeed"); test.into_bytes() }; assert_eq!( re_serialized, bytes, "serialized value == original serialized bytes" ); } }