#![feature(array_try_from_fn)] #![feature(associated_type_bounds)] #![feature(iterator_try_collect)] pub use enumset; pub use flate2; pub use paste; #[cfg(feature = "random")] pub use generate_random; #[cfg(feature = "random")] pub use rand; #[cfg(feature = "serde")] pub use serde; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use enumset::{EnumSet, EnumSetType, EnumSetTypeWithRepr}; use mt_data_derive::mt_derive; pub use mt_data_derive::{MtDeserialize, MtSerialize}; use paste::paste as paste_macro; use std::{ collections::{HashMap, HashSet}, convert::Infallible, fmt, io::{self, Read, Write}, num::TryFromIntError, ops::Deref, }; use thiserror::Error; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[cfg(feature = "random")] use generate_random::GenerateRandom; #[cfg(any(feature = "client", feature = "server"))] use crate as mt_data; #[derive(Error, Debug)] pub enum SerializeError { #[error("io error: {0}")] IoError(#[from] io::Error), #[error("collection too big: {0}")] TooBig(#[from] TryFromIntError), } impl From for SerializeError { fn from(_err: Infallible) -> Self { unreachable!("infallible") } } #[derive(Error, Debug)] pub enum DeserializeError { #[error("io error: {0}")] IoError(io::Error), #[error("unexpected end of file")] UnexpectedEof, #[error("collection too big: {0}")] TooBig(#[from] TryFromIntError), #[error("invalid UTF-16: {0}")] InvalidUtf16(#[from] std::char::DecodeUtf16Error), #[error("unimplemented")] Unimplemented, } impl From for DeserializeError { fn from(_err: Infallible) -> Self { unreachable!("infallible") } } impl From for DeserializeError { fn from(err: io::Error) -> Self { if err.kind() == io::ErrorKind::UnexpectedEof { DeserializeError::UnexpectedEof } else { DeserializeError::IoError(err) } } } pub trait OrDefault { fn or_default(self) -> Self; } impl OrDefault for Result { fn or_default(self) -> Self { match self { Err(DeserializeError::UnexpectedEof) => Ok(T::default()), x => x, } } } pub trait MtCfg: Sized + MtSerialize + MtDeserialize + TryFrom> { type Range: Iterator + 'static; fn utf16() -> bool { false } fn var_len() -> bool; fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> { Self::try_from(len) .map_err(Into::into)? .mt_serialize::(writer) } fn read_len(reader: &mut impl Read) -> Result; } trait MtCfgLen: Sized + MtSerialize + MtDeserialize + TryFrom> + TryInto> { } impl MtCfg for T { type Range = std::ops::Range; fn var_len() -> bool { false } fn read_len(reader: &mut impl Read) -> Result { let len = Self::mt_deserialize::(reader)? .try_into() .map_err(Into::into)?; Ok(0..len) } } pub type DefCfg = u16; pub trait MtSerialize: Sized { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError>; } pub trait MtDeserialize: Sized { fn mt_deserialize(reader: &mut impl Read) -> Result; } impl MtCfgLen for u8 {} impl MtCfgLen for u16 {} impl MtCfgLen for u32 {} impl MtCfgLen for u64 {} #[derive(Debug)] pub struct NoLen; impl MtSerialize for NoLen { fn mt_serialize(&self, _writer: &mut impl Write) -> Result<(), SerializeError> { Ok(()) } } impl MtDeserialize for NoLen { fn mt_deserialize(_reader: &mut impl Read) -> Result { Ok(Self) } } impl TryFrom for NoLen { type Error = Infallible; fn try_from(_x: usize) -> Result { Ok(Self) } } impl MtCfg for NoLen { fn var_len() -> bool { true } type Range = std::ops::RangeFrom; fn read_len(_reader: &mut impl Read) -> Result { Ok(0..) } } pub struct Utf16(pub B); impl MtSerialize for Utf16 { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { self.0.mt_serialize::(writer) } } impl MtDeserialize for Utf16 { fn mt_deserialize(reader: &mut impl Read) -> Result { Ok(Self(B::mt_deserialize::(reader)?)) } } impl TryFrom for Utf16 { type Error = >::Error; fn try_from(x: usize) -> Result { Ok(Self(x.try_into()?)) } } impl MtCfg for Utf16 { type Range = B::Range; fn utf16() -> bool { true } fn var_len() -> bool { B::var_len() } fn read_len(reader: &mut impl Read) -> Result { B::read_len(reader) } } impl MtSerialize for u8 { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { writer.write_u8(*self)?; Ok(()) } } impl MtDeserialize for u8 { fn mt_deserialize(reader: &mut impl Read) -> Result { Ok(reader.read_u8()?) } } impl MtSerialize for i8 { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { writer.write_i8(*self)?; Ok(()) } } impl MtDeserialize for i8 { fn mt_deserialize(reader: &mut impl Read) -> Result { Ok(reader.read_i8()?) } } macro_rules! impl_num { ($T:ty) => { impl MtSerialize for $T { fn mt_serialize( &self, writer: &mut impl Write, ) -> Result<(), SerializeError> { paste_macro! { writer.[]::(*self)?; } Ok(()) } } impl MtDeserialize for $T { fn mt_deserialize(reader: &mut impl Read) -> Result { paste_macro! { Ok(reader.[]::()?) } } } }; } impl_num!(u16); impl_num!(i16); impl_num!(u32); impl_num!(i32); impl_num!(f32); impl_num!(u64); impl_num!(i64); impl_num!(f64); impl MtSerialize for () { fn mt_serialize(&self, _writer: &mut impl Write) -> Result<(), SerializeError> { Ok(()) } } impl MtDeserialize for () { fn mt_deserialize(_reader: &mut impl Read) -> Result { Ok(()) } } impl MtSerialize for bool { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { (*self as u8).mt_serialize::(writer) } } impl MtDeserialize for bool { fn mt_deserialize(reader: &mut impl Read) -> Result { Ok(u8::mt_deserialize::(reader)? != 0) } } impl MtSerialize for &T { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { (*self).mt_serialize::(writer) } } fn mt_serialize_seq( writer: &mut impl Write, iter: impl ExactSizeIterator + IntoIterator, ) -> Result<(), SerializeError> { C::write_len(iter.len(), writer)?; iter.into_iter() .try_for_each(|item| item.mt_serialize::(writer)) } fn mt_deserialize_seq<'a, C: MtCfg, T: MtDeserialize>( reader: &'a mut impl Read, ) -> Result> + 'a, DeserializeError> { Ok(C::read_len(reader)? .into_iter() .map_while(|_| match T::mt_deserialize::(reader) { Err(DeserializeError::UnexpectedEof) if C::var_len() => None, x => Some(x), })) } impl MtSerialize for [T; N] { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { mt_serialize_seq::(writer, self.iter()) } } impl MtDeserialize for [T; N] { fn mt_deserialize(reader: &mut impl Read) -> Result { std::array::try_from_fn(|_| T::mt_deserialize::(reader)) } } impl> MtSerialize for EnumSet { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { self.as_repr().mt_serialize::(writer) } } impl> MtDeserialize for EnumSet { fn mt_deserialize(reader: &mut impl Read) -> Result { Ok(Self::from_repr_truncated(T::mt_deserialize::( reader, )?)) } } impl MtSerialize for Option { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { match self { Some(item) => item.mt_serialize::(writer), None => Ok(()), } } } impl MtDeserialize for Option { fn mt_deserialize(reader: &mut impl Read) -> Result { T::mt_deserialize::(reader).map(Some).or_default() } } impl MtSerialize for Vec { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { mt_serialize_seq::(writer, self.iter()) } } impl MtDeserialize for Vec { fn mt_deserialize(reader: &mut impl Read) -> Result { mt_deserialize_seq::(reader)?.try_collect() } } impl MtSerialize for HashSet { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { mt_serialize_seq::(writer, self.iter()) } } impl MtDeserialize for HashSet { fn mt_deserialize(reader: &mut impl Read) -> Result { mt_deserialize_seq::(reader)?.try_collect() } } impl MtSerialize for (A, B) { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { self.0.mt_serialize::(writer)?; self.1.mt_serialize::(writer)?; Ok(()) } } impl MtDeserialize for (A, B) { fn mt_deserialize(reader: &mut impl Read) -> Result { let a = A::mt_deserialize::(reader)?; let b = B::mt_deserialize::(reader)?; Ok((a, b)) } } impl MtSerialize for HashMap where K: MtSerialize + std::cmp::Eq + std::hash::Hash, V: MtSerialize, { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { mt_serialize_seq::(writer, self.iter()) } } impl MtDeserialize for HashMap where K: MtDeserialize + std::cmp::Eq + std::hash::Hash, V: MtDeserialize, { fn mt_deserialize(reader: &mut impl Read) -> Result { mt_deserialize_seq::(reader)?.try_collect() } } impl MtSerialize for String { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { if C::utf16() { self.encode_utf16() .collect::>() // FIXME: is this allocation necessary? .mt_serialize::(writer) } else { mt_serialize_seq::(writer, self.as_bytes().iter()) } } } impl MtDeserialize for String { fn mt_deserialize(reader: &mut impl Read) -> Result { if C::utf16() { let mut err = None; let res = char::decode_utf16(mt_deserialize_seq::(reader)?.map_while(|x| match x { Ok(v) => Some(v), Err(e) => { err = Some(e); None } })) .try_collect(); match err { None => Ok(res?), Some(e) => Err(e), } } else { // TODO: UTF-8 decode Ok("".into()) } } } impl MtSerialize for Box { fn mt_serialize(&self, writer: &mut impl Write) -> Result<(), SerializeError> { self.deref().mt_serialize::(writer) } } impl MtDeserialize for Box { fn mt_deserialize(reader: &mut impl Read) -> Result { Ok(Self::new(T::mt_deserialize::(reader)?)) } } mod to_clt; mod to_srv; pub use to_clt::*; pub use to_srv::*;