Pumpkin/pumpkin-protocol/src/ser/mod.rs
2026-05-05 20:29:55 +02:00

747 lines
26 KiB
Rust

use core::str;
use serde::Serialize;
use std::io::{Read, Write};
use crate::{
FixedBitSet,
codec::{
bit_set::BitSet, var_int::VarInt, var_long::VarLong, var_uint::VarUInt, var_ulong::VarULong,
},
};
pub mod deserializer;
use pumpkin_nbt::{serializer::WriteAdaptor, tag::NbtTag};
use pumpkin_util::math::position::BlockPos;
use thiserror::Error;
pub mod serializer;
#[derive(Debug, Error)]
pub enum ReadingError {
#[error("EOF, Tried to read {0} but No bytes left to consume")]
CleanEOF(String),
#[error("incomplete: {0}")]
Incomplete(String),
#[error("too large: {0}")]
TooLarge(String),
#[error("{0}")]
Message(String),
}
#[derive(Debug, Error)]
pub enum WritingError {
#[error("IO error: {0}")]
IoError(std::io::Error),
#[error("Serde failure: {0}")]
Serde(String),
#[error("Failed to serialize packet: {0}")]
Message(String),
}
pub trait NetworkReadExt {
fn get_i8(&mut self) -> Result<i8, ReadingError>;
fn get_u8(&mut self) -> Result<u8, ReadingError>;
fn get_i16_be(&mut self) -> Result<i16, ReadingError>;
fn get_u16_be(&mut self) -> Result<u16, ReadingError>;
fn get_i32_be(&mut self) -> Result<i32, ReadingError>;
fn get_u32_be(&mut self) -> Result<u32, ReadingError>;
fn get_i64_be(&mut self) -> Result<i64, ReadingError>;
fn get_u64_be(&mut self) -> Result<u64, ReadingError>;
fn get_f32_be(&mut self) -> Result<f32, ReadingError>;
fn get_f64_be(&mut self) -> Result<f64, ReadingError>;
fn get_i128_be(&mut self) -> Result<i128, ReadingError>;
fn get_u128_be(&mut self) -> Result<u128, ReadingError>;
fn read_boxed_slice(&mut self, count: usize) -> Result<Box<[u8]>, ReadingError>;
fn read_remaining_to_boxed_slice(&mut self, bound: usize) -> Result<Box<[u8]>, ReadingError>;
fn get_bool(&mut self) -> Result<bool, ReadingError>;
fn get_var_int(&mut self) -> Result<VarInt, ReadingError>;
fn get_var_uint(&mut self) -> Result<VarUInt, ReadingError>;
fn get_var_long(&mut self) -> Result<VarLong, ReadingError>;
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError>;
fn get_string_bounded(&mut self, bound: usize) -> Result<String, ReadingError>;
fn get_string(&mut self) -> Result<String, ReadingError>;
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError>;
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError>;
fn get_option<G>(
&mut self,
parse: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
) -> Result<Option<G>, ReadingError>;
fn get_list<G>(
&mut self,
parse: impl Fn(&mut Self) -> Result<G, ReadingError>,
) -> Result<Vec<G>, ReadingError>;
}
macro_rules! get_number_be {
($name:ident, $type:ty) => {
fn $name(&mut self) -> Result<$type, ReadingError> {
let mut buf = [0u8; std::mem::size_of::<$type>()];
self.read_exact(&mut buf)
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
Ok(<$type>::from_be_bytes(buf))
}
};
}
impl<R: Read> NetworkReadExt for R {
get_number_be!(get_u8, u8);
get_number_be!(get_i8, i8);
get_number_be!(get_i16_be, i16);
get_number_be!(get_u16_be, u16);
get_number_be!(get_i32_be, i32);
get_number_be!(get_u32_be, u32);
get_number_be!(get_i64_be, i64);
get_number_be!(get_u64_be, u64);
get_number_be!(get_i128_be, i128);
get_number_be!(get_u128_be, u128);
get_number_be!(get_f32_be, f32);
get_number_be!(get_f64_be, f64);
fn read_boxed_slice(&mut self, length: usize) -> Result<Box<[u8]>, ReadingError> {
// Increase this to at least 2MB to handle larger Bedrock batches
const MAX_SLICE_LENGTH: usize = 2 * 1024 * 1024; // 2MB
if !(0..=MAX_SLICE_LENGTH).contains(&length) {
return Err(ReadingError::Message(format!(
"read_boxed_slice: length {length} out of bounds"
)));
}
let mut buf = vec![0u8; length];
self.read_exact(&mut buf)
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
Ok(buf.into())
}
fn read_remaining_to_boxed_slice(&mut self, bound: usize) -> Result<Box<[u8]>, ReadingError> {
let mut return_buf = Vec::new();
// Take one extra byte to check for exceeding bound
self.take(bound as u64 + 1)
.read_to_end(&mut return_buf)
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
if return_buf.len() > bound {
return Err(ReadingError::TooLarge(
"Read remaining too long".to_string(),
));
}
Ok(return_buf.into_boxed_slice())
}
fn get_bool(&mut self) -> Result<bool, ReadingError> {
let byte = self.get_u8()?;
Ok(byte != 0)
}
fn get_var_int(&mut self) -> Result<VarInt, ReadingError> {
VarInt::decode(self)
}
fn get_var_uint(&mut self) -> Result<VarUInt, ReadingError> {
VarUInt::decode(self)
}
fn get_var_long(&mut self) -> Result<VarLong, ReadingError> {
VarLong::decode(self)
}
fn get_var_ulong(&mut self) -> Result<VarULong, ReadingError> {
VarULong::decode(self)
}
fn get_string_bounded(&mut self, bound: usize) -> Result<String, ReadingError> {
let bytes_len = self.get_var_uint()?.0 as usize;
// We treat `bound` as the maximum number of Java `char`s allowed.
// First, check if there are too many bytes to even fit in the UTF-16 bound.
// 1 Java `char` takes a maximum of 3 bytes in UTF-8:
let maximum_utf8_bytes = bound.saturating_mul(3);
if bytes_len > maximum_utf8_bytes {
return Err(ReadingError::TooLarge(format!(
"string has too many bytes ({bytes_len} > {maximum_utf8_bytes})"
)));
}
let data = self.read_boxed_slice(bytes_len)?;
let string =
String::from_utf8(data.into()).map_err(|e| ReadingError::Message(e.to_string()))?;
// Next, if we're able to find the (bound + 1)th UTF-16 character, the string is too big.
if string.encode_utf16().nth(bound).is_some() {
return Err(ReadingError::TooLarge(format!(
"string has too many UTF-16 characters (more than the maximum limit {bound})"
)));
}
Ok(string)
}
fn get_string(&mut self) -> Result<String, ReadingError> {
self.get_string_bounded(i32::MAX as usize)
}
fn get_uuid(&mut self) -> Result<uuid::Uuid, ReadingError> {
let mut bytes = [0u8; 16];
self.read_exact(&mut bytes)
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
Ok(uuid::Uuid::from_bytes(bytes))
}
fn get_fixed_bitset(&mut self, bits: usize) -> Result<FixedBitSet, ReadingError> {
let bytes = self.read_boxed_slice(bits.div_ceil(8))?;
Ok(bytes)
}
fn get_option<G>(
&mut self,
parse: impl FnOnce(&mut Self) -> Result<G, ReadingError>,
) -> Result<Option<G>, ReadingError> {
if self.get_bool()? {
Ok(Some(parse(self)?))
} else {
Ok(None)
}
}
fn get_list<G>(
&mut self,
parse: impl Fn(&mut Self) -> Result<G, ReadingError>,
) -> Result<Vec<G>, ReadingError> {
const MAX_LIST_SIZE: usize = 65536;
let len = self.get_var_int()?.0 as usize;
if len > MAX_LIST_SIZE {
return Err(ReadingError::TooLarge(format!(
"List length {len} exceeds limit"
)));
}
let mut list = Vec::with_capacity(len);
for _ in 0..len {
list.push(parse(self)?);
}
Ok(list)
}
}
pub trait NetworkWriteExt {
fn write_i8(&mut self, data: i8) -> Result<(), WritingError>;
fn write_u8(&mut self, data: u8) -> Result<(), WritingError>;
fn write_i16_be(&mut self, data: i16) -> Result<(), WritingError>;
fn write_u16_be(&mut self, data: u16) -> Result<(), WritingError>;
fn write_i32_be(&mut self, data: i32) -> Result<(), WritingError>;
fn write_u32_be(&mut self, data: u32) -> Result<(), WritingError>;
fn write_i64_be(&mut self, data: i64) -> Result<(), WritingError>;
fn write_u64_be(&mut self, data: u64) -> Result<(), WritingError>;
fn write_f32_be(&mut self, data: f32) -> Result<(), WritingError>;
fn write_f64_be(&mut self, data: f64) -> Result<(), WritingError>;
fn write_slice(&mut self, data: &[u8]) -> Result<(), WritingError>;
fn write_bool(&mut self, data: bool) -> Result<(), WritingError> {
if data {
self.write_u8(1)
} else {
self.write_u8(0)
}
}
fn write_fixed_bitset(&mut self, bits: usize, bit_set: FixedBitSet)
-> Result<(), WritingError>;
fn write_var_int(&mut self, data: &VarInt) -> Result<(), WritingError>;
fn write_var_uint(&mut self, data: &VarUInt) -> Result<(), WritingError>;
fn write_var_long(&mut self, data: &VarLong) -> Result<(), WritingError>;
fn write_string_bounded(&mut self, data: &str, bound: usize) -> Result<(), WritingError>;
fn write_string(&mut self, data: &str) -> Result<(), WritingError>;
fn write_block_pos(&mut self, pos: &BlockPos) -> Result<(), WritingError>;
fn write_uuid(&mut self, data: &uuid::Uuid) -> Result<(), WritingError> {
let (first, second) = data.as_u64_pair();
self.write_u64_be(first)?;
self.write_u64_be(second)
}
fn write_bitset(&mut self, bitset: &BitSet) -> Result<(), WritingError>;
fn write_option<G>(
&mut self,
data: &Option<G>,
writer: impl FnOnce(&mut Self, &G) -> Result<(), WritingError>,
) -> Result<(), WritingError> {
if let Some(data) = data {
self.write_bool(true)?;
writer(self, data)
} else {
self.write_bool(false)
}
}
fn write_list<G>(
&mut self,
list: &[G],
writer: impl Fn(&mut Self, &G) -> Result<(), WritingError>,
) -> Result<(), WritingError> {
self.write_var_int(&(list.len() as i32).into())?;
for data in list {
writer(self, data)?;
}
Ok(())
}
fn write_serialize<G: Serialize>(&mut self, data: &G) -> Result<(), WritingError>
where
Self: Sized;
fn write_nbt(&mut self, data: NbtTag) -> Result<(), WritingError>;
}
macro_rules! write_number_be {
($name:ident, $type:ty) => {
fn $name(&mut self, data: $type) -> Result<(), WritingError> {
self.write_all(&data.to_be_bytes())
.map_err(WritingError::IoError)
}
};
}
impl<W: Write> NetworkWriteExt for W {
fn write_i8(&mut self, data: i8) -> Result<(), WritingError> {
self.write_all(&data.to_be_bytes())
.map_err(WritingError::IoError)
}
fn write_u8(&mut self, data: u8) -> Result<(), WritingError> {
self.write_all(&data.to_be_bytes())
.map_err(WritingError::IoError)
}
write_number_be!(write_i16_be, i16);
write_number_be!(write_u16_be, u16);
write_number_be!(write_i32_be, i32);
write_number_be!(write_u32_be, u32);
write_number_be!(write_i64_be, i64);
write_number_be!(write_u64_be, u64);
write_number_be!(write_f32_be, f32);
write_number_be!(write_f64_be, f64);
fn write_slice(&mut self, data: &[u8]) -> Result<(), WritingError> {
self.write_all(data).map_err(WritingError::IoError)
}
fn write_fixed_bitset(
&mut self,
bits: usize,
bit_set: FixedBitSet,
) -> Result<(), WritingError> {
let new_length = bits.div_ceil(8);
let mut new_vec = vec![0u8; new_length];
let bytes_to_copy = std::cmp::min(bit_set.len(), new_length);
new_vec[..bytes_to_copy].copy_from_slice(&bit_set[..bytes_to_copy]);
self.write_slice(&new_vec)?;
Ok(())
}
fn write_var_int(&mut self, data: &VarInt) -> Result<(), WritingError> {
data.encode(self)
}
fn write_var_uint(&mut self, data: &VarUInt) -> Result<(), WritingError> {
data.encode(self)
}
fn write_var_long(&mut self, data: &VarLong) -> Result<(), WritingError> {
data.encode(self)
}
fn write_string_bounded(&mut self, data: &str, bound: usize) -> Result<(), WritingError> {
if data.len() > bound {
return Err(WritingError::Message(format!(
"string length {} exceeds bound {}",
data.len(),
bound
)));
}
self.write_var_int(&data.len().try_into().map_err(|_| {
WritingError::Message(format!("{} isn't representable as a VarInt", data.len()))
})?)?;
self.write_all(data.as_bytes())
.map_err(WritingError::IoError)
}
fn write_string(&mut self, data: &str) -> Result<(), WritingError> {
self.write_string_bounded(data, i16::MAX as usize)
}
fn write_block_pos(&mut self, pos: &BlockPos) -> Result<(), WritingError> {
self.write_i64_be(pos.as_long())
}
fn write_bitset(&mut self, data: &BitSet) -> Result<(), WritingError> {
data.encode(self)
}
fn write_option<G>(
&mut self,
data: &Option<G>,
writer: impl FnOnce(&mut Self, &G) -> Result<(), WritingError>,
) -> Result<(), WritingError> {
if let Some(data) = data {
self.write_bool(true)?;
writer(self, data)
} else {
self.write_bool(false)
}
}
fn write_list<G>(
&mut self,
list: &[G],
writer: impl Fn(&mut Self, &G) -> Result<(), WritingError>,
) -> Result<(), WritingError> {
self.write_var_int(&(list.len() as i32).into())?;
for data in list {
writer(self, data)?;
}
Ok(())
}
fn write_serialize<G: Serialize>(&mut self, data: &G) -> Result<(), WritingError> {
let mut serializer = serializer::Serializer::new(self);
data.serialize(&mut serializer)
}
fn write_nbt(&mut self, data: NbtTag) -> Result<(), WritingError> {
let mut write_adaptor = WriteAdaptor::new(self);
data.serialize(&mut write_adaptor)
.map_err(|e| WritingError::Message(e.to_string()))?;
Ok(())
}
}
#[cfg(test)]
mod test {
use std::io::Cursor;
use serde::{Deserialize, Serialize};
use crate::{
VarInt,
ser::{deserializer, serializer},
};
#[test]
fn i32_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug)]
struct Foo {
bar: i32,
}
let foo = Foo { bar: 69 };
let mut bytes = Vec::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
foo.serialize(&mut serializer)?;
let cursor = Cursor::new(bytes);
let deserialized: Foo = Foo::deserialize(&mut deserializer::Deserializer::new(cursor))?;
assert_eq!(foo, deserialized);
Ok(())
}
#[test]
fn varint_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug)]
struct Foo {
bar: VarInt,
}
let foo = Foo { bar: 69.into() };
let mut bytes = Vec::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
foo.serialize(&mut serializer)?;
let cursor = Cursor::new(bytes);
let deserialized: Foo = Foo::deserialize(&mut deserializer::Deserializer::new(cursor))?;
assert_eq!(foo, deserialized);
Ok(())
}
#[test]
fn char_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct CharStruct {
c: char,
}
// Test with normal char
let original = CharStruct { c: 'A' };
let mut bytes = Vec::new();
let mut ser = serializer::Serializer::new(&mut bytes);
original.serialize(&mut ser)?;
assert_eq!(bytes, vec![0, 0, 0, 0x41]);
let de_cursor = Cursor::new(bytes);
let deserialized: CharStruct =
CharStruct::deserialize(&mut deserializer::Deserializer::new(de_cursor))?;
assert_eq!(original, deserialized);
// Test with complex char
let original_complex = CharStruct { c: 'Ω' }; // Greek Omega, U+03A9
let mut bytes_complex = Vec::new();
let mut ser_complex = serializer::Serializer::new(&mut bytes_complex);
original_complex.serialize(&mut ser_complex)?;
assert_eq!(bytes_complex, vec![0, 0, 0x03, 0xA9]);
let de_cursor_complex = Cursor::new(bytes_complex);
let deserialized_complex: CharStruct =
CharStruct::deserialize(&mut deserializer::Deserializer::new(de_cursor_complex))?;
assert_eq!(original_complex, deserialized_complex);
// Test with an emoji
let original_emoji = CharStruct { c: '\u{1F383}' }; // Pumpkin emoji, U+1F383
let mut bytes_emoji = Vec::new();
let mut ser_emoji = serializer::Serializer::new(&mut bytes_emoji);
original_emoji.serialize(&mut ser_emoji)?;
assert_eq!(bytes_emoji, vec![0, 0x01, 0xF3, 0x83]);
let de_cursor_emoji = Cursor::new(bytes_emoji);
let deserialized_emoji: CharStruct =
CharStruct::deserialize(&mut deserializer::Deserializer::new(de_cursor_emoji))?;
assert_eq!(original_emoji, deserialized_emoji);
Ok(())
}
#[test]
fn i128_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct I128Struct {
val: i128,
}
let original = I128Struct {
val: 12345678901234567890123456789012345678,
};
let mut bytes = Vec::new();
let mut ser = serializer::Serializer::new(&mut bytes);
original.serialize(&mut ser)?;
assert_eq!(bytes, original.val.to_be_bytes());
let de_cursor = Cursor::new(bytes);
let deserialized: I128Struct =
I128Struct::deserialize(&mut deserializer::Deserializer::new(de_cursor))?;
assert_eq!(original, deserialized);
let original_neg = I128Struct {
val: -12345678901234567890123456789012345678,
};
let mut bytes_neg = Vec::new();
let mut ser_neg = serializer::Serializer::new(&mut bytes_neg);
original_neg.serialize(&mut ser_neg)?;
assert_eq!(bytes_neg, original_neg.val.to_be_bytes());
let de_cursor_neg = Cursor::new(bytes_neg);
let deserialized_neg: I128Struct =
I128Struct::deserialize(&mut deserializer::Deserializer::new(de_cursor_neg))?;
assert_eq!(original_neg, deserialized_neg);
Ok(())
}
#[test]
fn u128_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct U128Struct {
val: u128,
}
let original = U128Struct {
val: 123456789012345678901234567890123456789,
};
let mut bytes = Vec::new();
let mut ser = serializer::Serializer::new(&mut bytes);
original.serialize(&mut ser)?;
assert_eq!(bytes, original.val.to_be_bytes());
let de_cursor = Cursor::new(bytes);
let deserialized: U128Struct =
U128Struct::deserialize(&mut deserializer::Deserializer::new(de_cursor))?;
assert_eq!(original, deserialized);
Ok(())
}
#[test]
fn unit_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct UnitStruct;
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct StructWithUnit {
a: i32,
b: UnitStruct,
c: i32,
}
let original = UnitStruct;
let mut bytes = Vec::new();
let mut ser = serializer::Serializer::new(&mut bytes);
original.serialize(&mut ser)?;
assert!(bytes.is_empty());
let de_cursor = Cursor::new(bytes);
let deserialized: UnitStruct =
UnitStruct::deserialize(&mut deserializer::Deserializer::new(de_cursor))?;
assert_eq!(original, deserialized);
let original_with_unit = StructWithUnit {
a: 1,
b: UnitStruct,
c: 2,
};
let mut bytes_with_unit = Vec::new();
let mut ser_with_unit = serializer::Serializer::new(&mut bytes_with_unit);
original_with_unit.serialize(&mut ser_with_unit)?;
// Check that only a and c were serialized
let mut expected_bytes = Vec::new();
expected_bytes.extend_from_slice(&1i32.to_be_bytes());
expected_bytes.extend_from_slice(&2i32.to_be_bytes());
assert_eq!(bytes_with_unit, expected_bytes);
let de_cursor_with_unit = Cursor::new(bytes_with_unit);
let deserialized_with_unit: StructWithUnit =
StructWithUnit::deserialize(&mut deserializer::Deserializer::new(de_cursor_with_unit))?;
assert_eq!(original_with_unit, deserialized_with_unit);
Ok(())
}
#[test]
fn enum_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
enum MyEnum {
A,
B(i32),
C { x: i32, y: String },
}
let original_a = MyEnum::A;
let mut bytes_a = Vec::new();
let mut ser_a = serializer::Serializer::new(&mut bytes_a);
original_a.serialize(&mut ser_a)?;
// VarInt for index 0
assert_eq!(bytes_a, vec![0x00]);
let de_cursor_a = Cursor::new(bytes_a);
let deserialized_a: MyEnum =
MyEnum::deserialize(&mut deserializer::Deserializer::new(de_cursor_a))?;
assert_eq!(original_a, deserialized_a);
let original_b = MyEnum::B(123);
let mut bytes_b = Vec::new();
let mut ser_b = serializer::Serializer::new(&mut bytes_b);
original_b.serialize(&mut ser_b)?;
// VarInt for index 1, then i32 for 123
let mut expected_bytes_b = vec![0x01];
expected_bytes_b.extend_from_slice(&123i32.to_be_bytes());
assert_eq!(bytes_b, expected_bytes_b);
let de_cursor_b = Cursor::new(bytes_b);
let deserialized_b: MyEnum =
MyEnum::deserialize(&mut deserializer::Deserializer::new(de_cursor_b))?;
assert_eq!(original_b, deserialized_b);
let original_c = MyEnum::C {
x: 456,
y: "hello".to_string(),
};
let mut bytes_c = Vec::new();
let mut ser_c = serializer::Serializer::new(&mut bytes_c);
original_c.serialize(&mut ser_c)?;
// VarInt for index 2, then i32 for 456, then string "hello"
let mut expected_bytes_c = vec![0x02];
expected_bytes_c.extend_from_slice(&456i32.to_be_bytes());
expected_bytes_c.push(0x05); // VarInt for string length 5
expected_bytes_c.extend_from_slice(b"hello");
assert_eq!(bytes_c, expected_bytes_c);
let de_cursor_c = Cursor::new(bytes_c);
let deserialized_c: MyEnum =
MyEnum::deserialize(&mut deserializer::Deserializer::new(de_cursor_c))?;
assert_eq!(original_c, deserialized_c);
Ok(())
}
#[test]
fn tuple_struct_reserialize() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct MyTupleStruct(i32, String);
let original = MyTupleStruct(789, "world".to_string());
let mut bytes = Vec::new();
let mut ser = serializer::Serializer::new(&mut bytes);
original.serialize(&mut ser)?;
let mut expected_bytes = Vec::new();
expected_bytes.extend_from_slice(&789i32.to_be_bytes());
expected_bytes.push(0x05); // VarInt for string length 5
expected_bytes.extend_from_slice(b"world");
assert_eq!(bytes, expected_bytes);
let de_cursor = Cursor::new(bytes);
let deserialized: MyTupleStruct =
MyTupleStruct::deserialize(&mut deserializer::Deserializer::new(de_cursor))?;
assert_eq!(original, deserialized);
Ok(())
}
#[test]
fn map_reserialize() -> Result<(), Box<dyn std::error::Error>> {
use std::collections::HashMap;
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct MyMapStruct {
map: HashMap<String, i32>,
}
let mut map = HashMap::new();
map.insert("one".to_string(), 1);
map.insert("two".to_string(), 2);
let original = MyMapStruct { map };
let mut bytes = Vec::new();
let mut serializer = serializer::Serializer::new(&mut bytes);
original.serialize(&mut serializer)?;
// Expected bytes: VarInt for map length (2), then key1, value1, key2, value2
// Order of elements in HashMap is not guaranteed, so we check deserialized content
let de_cursor = Cursor::new(bytes.clone()); // Clone bytes for potential debug
let deserialized: MyMapStruct =
MyMapStruct::deserialize(&mut deserializer::Deserializer::new(de_cursor))?;
assert_eq!(original.map.len(), deserialized.map.len());
for (k, v) in original.map {
assert_eq!(deserialized.map.get(&k), Some(&v));
}
// Test with an empty map
let empty_map_original = MyMapStruct {
map: HashMap::new(),
};
let mut empty_map_bytes = Vec::new();
let mut empty_map_ser = serializer::Serializer::new(&mut empty_map_bytes);
empty_map_original.serialize(&mut empty_map_ser)?;
assert_eq!(empty_map_bytes, vec![0x00]); // VarInt for length 0
let empty_map_de_cursor = Cursor::new(empty_map_bytes);
let empty_map_deserialized: MyMapStruct =
MyMapStruct::deserialize(&mut deserializer::Deserializer::new(empty_map_de_cursor))?;
assert_eq!(empty_map_original, empty_map_deserialized);
Ok(())
}
}