endecode 0.2.0

A simple encoding crate for types.
Documentation
use paste::paste;
use std::{collections::HashMap, marker::PhantomData, rc::Rc};

pub trait Encode {
    fn encode_internal(&self, vec: &mut Vec<u8>);
    fn encode(&self) -> Vec<u8> {
        let mut vec = vec![];
        self.encode_internal(&mut vec);
        vec
    }
}

macro_rules! impl_num {
    ($($type:ty),+) => {
        $(
            impl Encode for $type {
                fn encode_internal(&self, vec: &mut Vec<u8>) {
                    vec.extend(self.to_be_bytes());
                }
            }
        )+
    };
}

impl_num!(u8, u16, u32, u64, u128, usize);
impl_num!(i8, i16, i32, i64, i128, isize);
impl_num!(f32, f64);

macro_rules! impl_tuple {
    ($($num:tt),*) => {
        paste! {
            impl<$([<T $num>]),*> Encode for ($([<T $num>],)*)
            where
                $(
                    [<T $num>]: Encode
                ),*
            {
                #[allow(unused_variables)]
                fn encode_internal(&self, vec: &mut Vec<u8>) {
                    $(
                        self.$num.encode_internal(vec);
                    )*
                }
            }
        }
    };
}

impl_tuple!();
impl_tuple!(0);
impl_tuple!(0, 1);
impl_tuple!(0, 1, 2);
impl_tuple!(0, 1, 2, 3);
impl_tuple!(0, 1, 2, 3, 4);
impl_tuple!(0, 1, 2, 3, 4, 5);
impl_tuple!(0, 1, 2, 3, 4, 5, 6);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
impl_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);

impl<T> Encode for PhantomData<T> {
    fn encode_internal(&self, _vec: &mut Vec<u8>) {}
}

impl Encode for bool {
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        vec.push(*self as u8);
    }
}

impl<T> Encode for Option<T>
where
    T: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.is_some().encode_internal(vec);
        if let Some(v) = self {
            v.encode_internal(vec);
        }
    }
}

impl Encode for String {
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.as_str().encode_internal(vec);
    }
}

impl Encode for &str {
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.as_bytes().encode_internal(vec);
    }
}

impl<T, const N: usize> Encode for [T; N]
where
    T: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        for i in self {
            i.encode_internal(vec);
        }
    }
}

impl<T> Encode for [T]
where
    T: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.len().encode_internal(vec);
        for i in self.iter() {
            i.encode_internal(vec);
        }
    }
}

impl<T> Encode for Vec<T>
where
    T: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.as_slice().encode_internal(vec);
    }
}

impl<K, V> Encode for HashMap<K, V>
where
    K: Encode,
    V: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.len().encode_internal(vec);
        for (k, v) in self.iter() {
            k.encode_internal(vec);
            v.encode_internal(vec);
        }
    }
}

impl<T> Encode for Rc<T>
where
    T: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.as_ref().encode_internal(vec);
    }
}

impl<T, E> Encode for Result<T, E>
where
    T: Encode,
    E: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.is_ok().encode_internal(vec);
        match self {
            Ok(ok) => ok.encode_internal(vec),
            Err(err) => err.encode_internal(vec),
        }
    }
}

impl<T> Encode for Box<T>
where
    T: Encode,
{
    fn encode_internal(&self, vec: &mut Vec<u8>) {
        self.as_ref().encode_internal(vec);
    }
}