use super::DeserializationError;
use crate::collections::*;
mod byte_reader;
pub use byte_reader::{ByteReader, SliceReader};
mod byte_writer;
pub use byte_writer::ByteWriter;
pub trait Serializable {
    fn write_into<W: ByteWriter>(&self, target: &mut W);
    fn to_bytes(&self) -> Vec<u8> {
        let mut result = Vec::with_capacity(self.get_size_hint());
        self.write_into(&mut result);
        result
    }
    fn get_size_hint(&self) -> usize {
        0
    }
}
impl<T: Serializable> Serializable for &T {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        (*self).write_into(target)
    }
}
impl Serializable for () {
    fn write_into<W: ByteWriter>(&self, _target: &mut W) {}
}
impl<T1> Serializable for (T1,)
where
    T1: Serializable,
{
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.0.write_into(target);
    }
}
impl<T1, T2> Serializable for (T1, T2)
where
    T1: Serializable,
    T2: Serializable,
{
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.0.write_into(target);
        self.1.write_into(target);
    }
}
impl<T1, T2, T3> Serializable for (T1, T2, T3)
where
    T1: Serializable,
    T2: Serializable,
    T3: Serializable,
{
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.0.write_into(target);
        self.1.write_into(target);
        self.2.write_into(target);
    }
}
impl<T1, T2, T3, T4> Serializable for (T1, T2, T3, T4)
where
    T1: Serializable,
    T2: Serializable,
    T3: Serializable,
    T4: Serializable,
{
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.0.write_into(target);
        self.1.write_into(target);
        self.2.write_into(target);
        self.3.write_into(target);
    }
}
impl<T1, T2, T3, T4, T5> Serializable for (T1, T2, T3, T4, T5)
where
    T1: Serializable,
    T2: Serializable,
    T3: Serializable,
    T4: Serializable,
    T5: Serializable,
{
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.0.write_into(target);
        self.1.write_into(target);
        self.2.write_into(target);
        self.3.write_into(target);
        self.4.write_into(target);
    }
}
impl<T1, T2, T3, T4, T5, T6> Serializable for (T1, T2, T3, T4, T5, T6)
where
    T1: Serializable,
    T2: Serializable,
    T3: Serializable,
    T4: Serializable,
    T5: Serializable,
    T6: Serializable,
{
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.0.write_into(target);
        self.1.write_into(target);
        self.2.write_into(target);
        self.3.write_into(target);
        self.4.write_into(target);
        self.5.write_into(target);
    }
}
impl Serializable for u8 {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_u8(*self);
    }
}
impl Serializable for u16 {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_u16(*self);
    }
}
impl Serializable for u32 {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_u32(*self);
    }
}
impl Serializable for u64 {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_u64(*self);
    }
}
impl Serializable for u128 {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_u128(*self);
    }
}
impl Serializable for usize {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_usize(*self)
    }
}
impl<T: Serializable> Serializable for Option<T> {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        match self {
            Some(v) => {
                target.write_bool(true);
                v.write_into(target);
            }
            None => target.write_bool(false),
        }
    }
}
impl<T: Serializable, const C: usize> Serializable for [T; C] {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_many(self)
    }
}
pub trait Deserializable: Sized {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError>;
    fn read_from_bytes(bytes: &[u8]) -> Result<Self, DeserializationError> {
        Self::read_from(&mut SliceReader::new(bytes))
    }
}
impl Deserializable for () {
    fn read_from<R: ByteReader>(_source: &mut R) -> Result<Self, DeserializationError> {
        Ok(())
    }
}
impl<T1> Deserializable for (T1,)
where
    T1: Deserializable,
{
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let v1 = T1::read_from(source)?;
        Ok((v1,))
    }
}
impl<T1, T2> Deserializable for (T1, T2)
where
    T1: Deserializable,
    T2: Deserializable,
{
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let v1 = T1::read_from(source)?;
        let v2 = T2::read_from(source)?;
        Ok((v1, v2))
    }
}
impl<T1, T2, T3> Deserializable for (T1, T2, T3)
where
    T1: Deserializable,
    T2: Deserializable,
    T3: Deserializable,
{
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let v1 = T1::read_from(source)?;
        let v2 = T2::read_from(source)?;
        let v3 = T3::read_from(source)?;
        Ok((v1, v2, v3))
    }
}
impl<T1, T2, T3, T4> Deserializable for (T1, T2, T3, T4)
where
    T1: Deserializable,
    T2: Deserializable,
    T3: Deserializable,
    T4: Deserializable,
{
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let v1 = T1::read_from(source)?;
        let v2 = T2::read_from(source)?;
        let v3 = T3::read_from(source)?;
        let v4 = T4::read_from(source)?;
        Ok((v1, v2, v3, v4))
    }
}
impl<T1, T2, T3, T4, T5> Deserializable for (T1, T2, T3, T4, T5)
where
    T1: Deserializable,
    T2: Deserializable,
    T3: Deserializable,
    T4: Deserializable,
    T5: Deserializable,
{
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let v1 = T1::read_from(source)?;
        let v2 = T2::read_from(source)?;
        let v3 = T3::read_from(source)?;
        let v4 = T4::read_from(source)?;
        let v5 = T5::read_from(source)?;
        Ok((v1, v2, v3, v4, v5))
    }
}
impl<T1, T2, T3, T4, T5, T6> Deserializable for (T1, T2, T3, T4, T5, T6)
where
    T1: Deserializable,
    T2: Deserializable,
    T3: Deserializable,
    T4: Deserializable,
    T5: Deserializable,
    T6: Deserializable,
{
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let v1 = T1::read_from(source)?;
        let v2 = T2::read_from(source)?;
        let v3 = T3::read_from(source)?;
        let v4 = T4::read_from(source)?;
        let v5 = T5::read_from(source)?;
        let v6 = T6::read_from(source)?;
        Ok((v1, v2, v3, v4, v5, v6))
    }
}
impl Deserializable for u8 {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        source.read_u8()
    }
}
impl Deserializable for u16 {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        source.read_u16()
    }
}
impl Deserializable for u32 {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        source.read_u32()
    }
}
impl Deserializable for u64 {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        source.read_u64()
    }
}
impl Deserializable for u128 {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        source.read_u128()
    }
}
impl Deserializable for usize {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        source.read_usize()
    }
}
impl<T: Deserializable> Deserializable for Option<T> {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let contains = source.read_bool()?;
        match contains {
            true => Ok(Some(T::read_from(source)?)),
            false => Ok(None),
        }
    }
}
impl<T: Deserializable, const C: usize> Deserializable for [T; C] {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let data: Vec<T> = source.read_many(C)?;
        let res = data.try_into().unwrap_or_else(|v: Vec<T>| {
            panic!("Expected a Vec of length {} but it was {}", C, v.len())
        });
        Ok(res)
    }
}