747 lines
26 KiB
Rust
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(())
|
|
}
|
|
}
|