-pub use enumset;
-pub use flate2;
-pub use paste::paste;
-
-#[cfg(feature = "random")]
-pub use generate_random;
-
-#[cfg(feature = "random")]
-pub use rand;
+#![feature(array_try_from_fn)]
+#![feature(associated_type_bounds)]
+#![feature(iterator_try_collect)]
-#[cfg(feature = "serde")]
-pub use serde;
+pub use flate2;
+pub use mt_ser_derive::{mt_derive, MtDeserialize, MtSerialize};
+pub use paste;
+pub use zstd;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
-use enumset::{EnumSet, EnumSetType, EnumSetTypeWithRepr};
-use mt_data_derive::mt_derive;
-pub use mt_data_derive::{MtDeserialize, MtSerialize};
+use enumset::{EnumSet, EnumSetTypeWithRepr};
+use paste::paste as paste_macro;
use std::{
collections::{HashMap, HashSet},
convert::Infallible,
- fmt,
+ fmt::Debug,
io::{self, Read, Write},
num::TryFromIntError,
- ops::Deref,
+ ops::{Deref, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
};
use thiserror::Error;
-#[cfg(feature = "serde")]
-use serde::{Deserialize, Serialize};
-
-#[cfg(feature = "random")]
-use generate_random::GenerateRandom;
-
-use crate as mt_data;
+#[cfg(test)]
+mod tests;
-#[derive(Error, Debug)]
-#[error("variable length")]
-pub struct VarLen;
+use crate as mt_ser;
#[derive(Error, Debug)]
pub enum SerializeError {
IoError(#[from] io::Error),
#[error("collection too big: {0}")]
TooBig(#[from] TryFromIntError),
- #[error("unimplemented")]
- Unimplemented,
+ #[error("{0}")]
+ Other(String),
}
-impl From<Infallible> for DeserializeError {
+impl From<Infallible> for SerializeError {
fn from(_err: Infallible) -> Self {
unreachable!("infallible")
}
#[derive(Error, Debug)]
pub enum DeserializeError {
#[error("io error: {0}")]
- IoError(#[from] io::Error),
- #[error("variable length not supported")]
- NoVarlen(#[from] VarLen),
+ IoError(io::Error),
+ #[error("unexpected end of file")]
+ UnexpectedEof,
#[error("collection too big: {0}")]
TooBig(#[from] TryFromIntError),
- #[error("unimplemented")]
- Unimplemented,
+ #[error("invalid UTF-16: {0}")]
+ InvalidUtf16(#[from] std::char::DecodeUtf16Error),
+ #[error("invalid {0} enum variant {1:?}")]
+ InvalidEnum(&'static str, Box<dyn Debug>),
+ #[error("invalid constant - wanted: {0:?} - got: {1:?}")]
+ InvalidConst(Box<dyn Debug>, Box<dyn Debug>),
+ #[error("{0}")]
+ Other(String),
}
-impl From<Infallible> for SerializeError {
+impl From<Infallible> for DeserializeError {
fn from(_err: Infallible) -> Self {
unreachable!("infallible")
}
}
-pub trait MtCfg:
- Sized
- + MtSerialize
- + MtDeserialize
- + TryFrom<usize, Error = Self::TryFromError>
- + TryInto<usize, Error = Self::TryIntoError>
-{
- type TryFromError: Into<SerializeError>;
- type TryIntoError: Into<DeserializeError>;
+impl From<io::Error> for DeserializeError {
+ fn from(err: io::Error) -> Self {
+ if err.kind() == io::ErrorKind::UnexpectedEof {
+ DeserializeError::UnexpectedEof
+ } else {
+ DeserializeError::IoError(err)
+ }
+ }
+}
- #[inline]
- fn utf16() -> bool {
- false
+pub trait OrDefault<T> {
+ fn or_default(self) -> Self;
+}
+
+pub struct WrapRead<'a, R: Read>(pub &'a mut R);
+impl<'a, R: Read> Read for WrapRead<'a, R> {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ self.0.read(buf)
}
- fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
- Ok(Self::try_from(len)
- .map_err(|e| e.into())?
- .mt_serialize::<DefCfg>(writer)?)
+ fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
+ self.0.read_vectored(bufs)
}
-}
-pub type DefCfg = u16;
+ /*
-pub trait MtSerialize: Sized {
- fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError>;
-}
+ fn is_read_vectored(&self) -> bool {
+ self.0.is_read_vectored()
+ }
-pub trait MtDeserialize: Sized {
- fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError>;
-}
+ */
-impl MtCfg for u8 {
- type TryFromError = TryFromIntError;
- type TryIntoError = Infallible;
-}
+ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+ self.0.read_to_end(buf)
+ }
+
+ fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
+ self.0.read_to_string(buf)
+ }
+
+ fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+ self.0.read_exact(buf)
+ }
+
+ /*
+
+ fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+ self.0.read_buf(buf)
+ }
-impl MtCfg for u16 {
- type TryFromError = TryFromIntError;
- type TryIntoError = Infallible;
+ fn read_buf_exact(&mut self, cursor: io::BorrowedCursor<'_>) -> io::Result<()> {
+ self.0.read_buf_exact(cursor)
+ }
+
+ */
}
-impl MtCfg for u32 {
- type TryFromError = TryFromIntError;
- type TryIntoError = TryFromIntError;
+impl<T: MtDeserialize + Default> OrDefault<T> for Result<T, DeserializeError> {
+ fn or_default(self) -> Self {
+ match self {
+ Err(DeserializeError::UnexpectedEof) => Ok(T::default()),
+ x => x,
+ }
+ }
}
-impl MtCfg for u64 {
- type TryFromError = TryFromIntError;
- type TryIntoError = TryFromIntError;
+pub trait MtLen {
+ fn option(&self) -> Option<usize>;
+
+ type Range: Iterator<Item = usize> + 'static;
+ fn range(&self) -> Self::Range;
+
+ type Take<R: Read>: Read;
+ fn take<R: Read>(&self, reader: R) -> Self::Take<R>;
}
-pub struct NoLen;
+pub trait MtCfg {
+ type Len: MtLen;
+ type Inner: MtCfg;
-impl MtSerialize for NoLen {
- fn mt_serialize<C: MtCfg>(&self, _writer: &mut impl Write) -> Result<(), SerializeError> {
- Ok(())
+ fn utf16() -> bool {
+ false
}
+
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError>;
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError>;
}
-impl MtDeserialize for NoLen {
- fn mt_deserialize<C: MtCfg>(_reader: &mut impl Read) -> Result<Self, DeserializeError> {
- Ok(Self)
- }
+pub trait MtSerialize {
+ fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError>;
}
-impl TryFrom<usize> for NoLen {
- type Error = Infallible;
+pub trait MtDeserialize: Sized {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError>;
+}
- fn try_from(_x: usize) -> Result<Self, Self::Error> {
- Ok(Self)
+impl MtLen for usize {
+ fn option(&self) -> Option<usize> {
+ Some(*self)
}
-}
-impl TryInto<usize> for NoLen {
- type Error = VarLen;
+ type Range = std::ops::Range<usize>;
+ fn range(&self) -> Self::Range {
+ 0..*self
+ }
- fn try_into(self) -> Result<usize, Self::Error> {
- Err(VarLen)
+ type Take<R: Read> = io::Take<R>;
+ fn take<R: Read>(&self, reader: R) -> Self::Take<R> {
+ reader.take(*self as u64)
}
}
-impl MtCfg for NoLen {
- type TryFromError = Infallible;
- type TryIntoError = VarLen;
+trait MtCfgLen:
+ Sized
+ + MtSerialize
+ + MtDeserialize
+ + TryFrom<usize, Error: Into<SerializeError>>
+ + TryInto<usize, Error: Into<DeserializeError>>
+{
}
-pub struct Utf16<B: MtCfg>(pub B);
+impl<T: MtCfgLen> MtCfg for T {
+ type Len = usize;
+ type Inner = DefCfg;
-impl<B: MtCfg> MtSerialize for Utf16<B> {
- fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- self.0.mt_serialize::<DefCfg>(writer)
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
+ Self::try_from(len)
+ .map_err(Into::into)?
+ .mt_serialize::<DefCfg>(writer)
}
-}
-impl<B: MtCfg> MtDeserialize for Utf16<B> {
- fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
- Ok(Self(B::mt_deserialize::<DefCfg>(reader)?))
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError> {
+ Self::mt_deserialize::<DefCfg>(reader)?
+ .try_into()
+ .map_err(Into::into)
}
}
-impl<B: MtCfg> TryFrom<usize> for Utf16<B> {
- type Error = B::TryFromError;
+impl MtCfgLen for u8 {}
+impl MtCfgLen for u16 {}
+impl MtCfgLen for u32 {}
+impl MtCfgLen for u64 {}
+
+pub type DefCfg = u16;
+
+impl MtCfg for () {
+ type Len = ();
+ type Inner = DefCfg;
+
+ fn write_len(_len: usize, _writer: &mut impl Write) -> Result<(), SerializeError> {
+ Ok(())
+ }
- fn try_from(x: usize) -> Result<Self, Self::Error> {
- Ok(Self(x.try_into()?))
+ fn read_len(_writer: &mut impl Read) -> Result<Self::Len, DeserializeError> {
+ Ok(())
}
}
-impl<B: MtCfg> TryInto<usize> for Utf16<B> {
- type Error = B::TryIntoError;
+impl MtLen for () {
+ fn option(&self) -> Option<usize> {
+ None
+ }
+
+ type Range = std::ops::RangeFrom<usize>;
+ fn range(&self) -> Self::Range {
+ 0..
+ }
- fn try_into(self) -> Result<usize, Self::Error> {
- self.0.try_into()
+ type Take<R: Read> = R;
+ fn take<R: Read>(&self, reader: R) -> Self::Take<R> {
+ reader
}
}
+pub struct Utf16<B: MtCfg = DefCfg>(pub B);
+
impl<B: MtCfg> MtCfg for Utf16<B> {
- type TryFromError = B::TryFromError;
- type TryIntoError = B::TryIntoError;
+ type Len = B::Len;
+ type Inner = B::Inner;
- #[inline]
fn utf16() -> bool {
true
}
+
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
+ B::write_len(len, writer)
+ }
+
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError> {
+ B::read_len(reader)
+ }
+}
+
+impl<A: MtCfg, B: MtCfg> MtCfg for (A, B) {
+ type Len = A::Len;
+ type Inner = B;
+
+ fn write_len(len: usize, writer: &mut impl Write) -> Result<(), SerializeError> {
+ A::write_len(len, writer)
+ }
+
+ fn read_len(reader: &mut impl Read) -> Result<Self::Len, DeserializeError> {
+ A::read_len(reader)
+ }
}
impl MtSerialize for u8 {
&self,
writer: &mut impl Write,
) -> Result<(), SerializeError> {
- paste! {
+ paste_macro! {
writer.[<write_ $T>]::<BigEndian>(*self)?;
}
Ok(())
impl MtDeserialize for $T {
fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
- paste! {
+ paste_macro! {
Ok(reader.[<read_ $T>]::<BigEndian>()?)
}
}
}
}
+impl MtDeserialize for () {
+ fn mt_deserialize<C: MtCfg>(_reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ Ok(())
+ }
+}
+
impl MtSerialize for bool {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
(*self as u8).mt_serialize::<DefCfg>(writer)
}
}
-impl<T: MtSerialize, const N: usize> MtSerialize for [T; N] {
+impl MtDeserialize for bool {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ Ok(u8::mt_deserialize::<DefCfg>(reader)? != 0)
+ }
+}
+
+impl<T: MtSerialize> MtSerialize for &T {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- self.as_slice().mt_serialize::<NoLen>(writer)
+ (*self).mt_serialize::<C>(writer)
}
}
-impl<T: MtSerialize> MtSerialize for &[T] {
+pub fn mt_serialize_seq<C: MtCfg, T: MtSerialize>(
+ writer: &mut impl Write,
+ iter: impl ExactSizeIterator + IntoIterator<Item = T>,
+) -> Result<(), SerializeError> {
+ C::write_len(iter.len(), writer)?;
+
+ iter.into_iter()
+ .try_for_each(|item| item.mt_serialize::<C::Inner>(writer))
+}
+
+pub fn mt_deserialize_seq<C: MtCfg, T: MtDeserialize>(
+ reader: &mut impl Read,
+) -> Result<impl Iterator<Item = Result<T, DeserializeError>> + '_, DeserializeError> {
+ let len = C::read_len(reader)?;
+ mt_deserialize_sized_seq::<C, _>(&len, reader)
+}
+
+pub fn mt_deserialize_sized_seq<'a, C: MtCfg, T: MtDeserialize>(
+ len: &C::Len,
+ reader: &'a mut impl Read,
+) -> Result<impl Iterator<Item = Result<T, DeserializeError>> + 'a, DeserializeError> {
+ let variable = len.option().is_none();
+
+ Ok(len
+ .range()
+ .map_while(move |_| match T::mt_deserialize::<C::Inner>(reader) {
+ Err(DeserializeError::UnexpectedEof) if variable => None,
+ x => Some(x),
+ }))
+}
+
+impl<T: MtSerialize, const N: usize> MtSerialize for [T; N] {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- C::write_len(self.len(), writer)?;
- for item in self.iter() {
- item.mt_serialize::<DefCfg>(writer)?;
- }
- Ok(())
+ mt_serialize_seq::<(), _>(writer, self.iter())
+ }
+}
+
+impl<T: MtDeserialize, const N: usize> MtDeserialize for [T; N] {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ std::array::try_from_fn(|_| T::mt_deserialize::<DefCfg>(reader))
}
}
}
}
+impl<T: MtDeserialize, E: EnumSetTypeWithRepr<Repr = T>> MtDeserialize for EnumSet<E> {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ Ok(Self::from_repr_truncated(T::mt_deserialize::<DefCfg>(
+ reader,
+ )?))
+ }
+}
+
impl<T: MtSerialize> MtSerialize for Option<T> {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
match self {
}
}
+impl<T: MtDeserialize> MtDeserialize for Option<T> {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ T::mt_deserialize::<C>(reader).map(Some).or_default()
+ }
+}
+
impl<T: MtSerialize> MtSerialize for Vec<T> {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- self.as_slice().mt_serialize::<C>(writer)
+ mt_serialize_seq::<C, _>(writer, self.iter())
}
}
-impl<T: MtSerialize> MtSerialize for HashSet<T> {
+impl<T: MtDeserialize> MtDeserialize for Vec<T> {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ mt_deserialize_seq::<C, _>(reader)?.try_collect()
+ }
+}
+
+impl<T: MtSerialize + std::cmp::Eq + std::hash::Hash> MtSerialize for HashSet<T> {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- C::write_len(self.len(), writer)?;
- for item in self.iter() {
- item.mt_serialize::<DefCfg>(writer)?;
- }
+ mt_serialize_seq::<C, _>(writer, self.iter())
+ }
+}
+
+impl<T: MtDeserialize + std::cmp::Eq + std::hash::Hash> MtDeserialize for HashSet<T> {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ mt_deserialize_seq::<C, _>(reader)?.try_collect()
+ }
+}
+
+// TODO: support more tuples
+impl<A: MtSerialize, B: MtSerialize> MtSerialize for (A, B) {
+ fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
+ self.0.mt_serialize::<C>(writer)?;
+ self.1.mt_serialize::<C::Inner>(writer)?;
+
Ok(())
}
}
+impl<A: MtDeserialize, B: MtDeserialize> MtDeserialize for (A, B) {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ let a = A::mt_deserialize::<C>(reader)?;
+ let b = B::mt_deserialize::<C::Inner>(reader)?;
+
+ Ok((a, b))
+ }
+}
+
impl<K, V> MtSerialize for HashMap<K, V>
where
K: MtSerialize + std::cmp::Eq + std::hash::Hash,
V: MtSerialize,
{
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
- C::write_len(self.len(), writer)?;
- for (key, value) in self.iter() {
- key.mt_serialize::<DefCfg>(writer)?;
- value.mt_serialize::<DefCfg>(writer)?;
- }
- Ok(())
+ mt_serialize_seq::<C, _>(writer, self.iter())
}
}
-impl MtSerialize for String {
+impl<K, V> MtDeserialize for HashMap<K, V>
+where
+ K: MtDeserialize + std::cmp::Eq + std::hash::Hash,
+ V: MtDeserialize,
+{
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ mt_deserialize_seq::<C, _>(reader)?.try_collect()
+ }
+}
+
+impl MtSerialize for &str {
fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
if C::utf16() {
self.encode_utf16()
- .collect::<Vec<_>>()
+ .collect::<Vec<_>>() // FIXME: is this allocation necessary?
.mt_serialize::<C>(writer)
} else {
- self.as_bytes().mt_serialize::<C>(writer)
+ mt_serialize_seq::<C, _>(writer, self.as_bytes().iter())
+ }
+ }
+}
+
+impl MtSerialize for String {
+ fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
+ self.as_str().mt_serialize::<C>(writer)
+ }
+}
+
+impl MtDeserialize for String {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ if C::utf16() {
+ let mut err = None;
+
+ let res =
+ char::decode_utf16(mt_deserialize_seq::<C, _>(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 {
+ let len = C::read_len(reader)?;
+
+ // use capacity if available
+ let mut st = match len.option() {
+ Some(x) => String::with_capacity(x),
+ None => String::new(),
+ };
+
+ len.take(WrapRead(reader)).read_to_string(&mut st)?;
+
+ Ok(st)
}
}
}
}
}
-mod to_clt;
-mod to_srv;
+impl<T: MtDeserialize> MtDeserialize for Box<T> {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ Ok(Self::new(T::mt_deserialize::<C>(reader)?))
+ }
+}
+
+#[derive(MtSerialize, MtDeserialize)]
+#[mt(typename = "Range")]
+#[allow(unused)]
+struct RemoteRange<T> {
+ start: T,
+ end: T,
+}
+
+#[derive(MtSerialize, MtDeserialize)]
+#[mt(typename = "RangeFrom")]
+#[allow(unused)]
+struct RemoteRangeFrom<T> {
+ start: T,
+}
+
+#[derive(MtSerialize, MtDeserialize)]
+#[mt(typename = "RangeFull")]
+#[allow(unused)]
+struct RemoteRangeFull;
+
+// RangeInclusive fields are private
+impl<T: MtSerialize> MtSerialize for RangeInclusive<T> {
+ fn mt_serialize<C: MtCfg>(&self, writer: &mut impl Write) -> Result<(), SerializeError> {
+ self.start().mt_serialize::<DefCfg>(writer)?;
+ self.end().mt_serialize::<DefCfg>(writer)?;
+
+ Ok(())
+ }
+}
+
+impl<T: MtDeserialize> MtDeserialize for RangeInclusive<T> {
+ fn mt_deserialize<C: MtCfg>(reader: &mut impl Read) -> Result<Self, DeserializeError> {
+ let start = T::mt_deserialize::<DefCfg>(reader)?;
+ let end = T::mt_deserialize::<DefCfg>(reader)?;
+
+ Ok(start..=end)
+ }
+}
+
+#[derive(MtSerialize, MtDeserialize)]
+#[mt(typename = "RangeTo")]
+#[allow(unused)]
+struct RemoteRangeTo<T> {
+ end: T,
+}
-pub use to_clt::*;
-pub use to_srv::*;
+#[derive(MtSerialize, MtDeserialize)]
+#[mt(typename = "RangeToInclusive")]
+#[allow(unused)]
+struct RemoteRangeToInclusive<T> {
+ end: T,
+}