use std::{
io::{self, Read, Write},
string::FromUtf8Error,
};
use thiserror::Error;
use uuid::Uuid;
use crate::varint::{VarInt, VarIntError, VarLong};
#[derive(Debug, Error)]
pub enum SerializationError {
#[error("VarInt/VarLong error: {0}")]
VarInt(#[from] VarIntError),
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("Invalid UTF-8: {0}")]
InvalidUtf8(#[from] FromUtf8Error),
#[error("String too long: {length} code units, maximum is {max}")]
StringTooLong {
length: usize,
max: usize,
},
#[error("Invalid enum discriminant: {0}")]
InvalidDiscriminant(i32),
#[error("Invalid length: {0}")]
InvalidLength(i64),
}
pub trait Serialize {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError>;
}
pub trait Deserialize: Sized {
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError>;
}
macro_rules! impl_primitive {
($t:ty) => {
impl Serialize for $t {
#[inline]
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
writer.write_all(&self.to_be_bytes())?;
Ok(())
}
}
impl Deserialize for $t {
#[inline]
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
let mut buf = [0u8; std::mem::size_of::<$t>()];
reader.read_exact(&mut buf)?;
Ok(<$t>::from_be_bytes(buf))
}
}
};
}
impl_primitive!(i8);
impl_primitive!(i16);
impl_primitive!(i32);
impl_primitive!(i64);
impl_primitive!(i128);
impl_primitive!(u8);
impl_primitive!(u16);
impl_primitive!(u32);
impl_primitive!(u64);
impl_primitive!(u128);
impl_primitive!(f32);
impl_primitive!(f64);
impl Serialize for bool {
#[inline]
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
writer.write_all(&[if *self { 0x01 } else { 0x00 }])?;
Ok(())
}
}
impl Deserialize for bool {
#[inline]
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf)?;
Ok(buf[0] != 0)
}
}
impl Serialize for VarInt {
#[inline]
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
self.write_sync(writer)?;
Ok(())
}
}
impl Deserialize for VarInt {
#[inline]
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
Ok(VarInt::read_sync(reader)?)
}
}
impl Serialize for VarLong {
#[inline]
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
self.write_sync(writer)?;
Ok(())
}
}
impl Deserialize for VarLong {
#[inline]
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
Ok(VarLong::read_sync(reader)?)
}
}
pub const MAX_STRING_LENGTH: usize = 32767;
pub fn serialize_string_with_max<W: Write + Unpin>(
s: &str,
writer: &mut W,
max_utf16: usize,
) -> Result<(), SerializationError> {
let utf16_len = s.encode_utf16().count();
if utf16_len > max_utf16 {
return Err(SerializationError::StringTooLong {
length: utf16_len,
max: max_utf16,
});
}
VarInt(s.len() as i32).write_sync(writer)?;
writer.write_all(s.as_bytes())?;
Ok(())
}
pub fn deserialize_string_with_max<R: Read + Unpin>(
reader: &mut R,
max_utf16: usize,
) -> Result<String, SerializationError> {
let byte_len = VarInt::read_sync(reader)?.0 as usize;
let mut buf = vec![0u8; byte_len];
reader.read_exact(&mut buf)?;
let s = String::from_utf8(buf)?;
let utf16_len = s.encode_utf16().count();
if utf16_len > max_utf16 {
return Err(SerializationError::StringTooLong {
length: utf16_len,
max: max_utf16,
});
}
Ok(s)
}
impl Serialize for String {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
serialize_string_with_max(self, writer, MAX_STRING_LENGTH)
}
}
impl Deserialize for String {
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
deserialize_string_with_max(reader, MAX_STRING_LENGTH)
}
}
impl Serialize for str {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
serialize_string_with_max(self, writer, MAX_STRING_LENGTH)
}
}
impl Serialize for Uuid {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
writer.write_all(self.as_bytes())?;
Ok(())
}
}
impl Deserialize for Uuid {
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
let mut buf = [0u8; 16];
reader.read_exact(&mut buf)?;
Ok(Uuid::from_bytes(buf))
}
}
impl<T: Serialize> Serialize for Option<T> {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
match self {
Some(v) => {
true.serialize(writer)?;
v.serialize(writer)?;
}
None => {
false.serialize(writer)?;
}
}
Ok(())
}
}
impl<T: Deserialize> Deserialize for Option<T> {
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
let present = bool::deserialize(reader)?;
if present {
Ok(Some(T::deserialize(reader)?))
} else {
Ok(None)
}
}
}
impl<T: Serialize> Serialize for Vec<T> {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
VarInt(self.len() as i32).write_sync(writer)?;
for item in self {
item.serialize(writer)?;
}
Ok(())
}
}
impl<T: Deserialize> Deserialize for Vec<T> {
fn deserialize<R: Read + Unpin>(reader: &mut R) -> Result<Self, SerializationError> {
let len = VarInt::read_sync(reader)?.0;
if len < 0 {
return Err(SerializationError::InvalidLength(len as i64));
}
let mut result = Vec::with_capacity(len as usize);
for _ in 0..len {
result.push(T::deserialize(reader)?);
}
Ok(result)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RawBytes(pub Vec<u8>);
impl RawBytes {
pub fn read_exact<R: Read + Unpin>(reader: &mut R, n: usize) -> Result<Self, SerializationError> {
let mut buf = vec![0u8; n];
reader.read_exact(&mut buf)?;
Ok(Self(buf))
}
}
impl Serialize for RawBytes {
fn serialize<W: Write + Unpin>(&self, writer: &mut W) -> Result<(), SerializationError> {
writer.write_all(&self.0)?;
Ok(())
}
}