serial_traits 1.1.2

A trait that allows you to serialize to and parse from Vec<u8> buffers. Comes with implementations for primitive types, String and generic collection types (if the item type implements the trait too.)
Documentation
use crate::unwrap_return;

// there is no type that all integers have which works nicely
// and lets us cast from/to our target types
// From<T> and Into<T> do not work
pub trait ExtensibleInteger {
    fn is_byte() -> bool;
    fn is_signed() -> bool;

    fn to_u8(&self) -> u8;
    fn from_u8(value: u8) -> Self;

    fn to_u128(&self) -> u128;
    fn from_u128(value: u128) -> Self;

    fn to_i128(&self) -> i128;
    fn from_i128(value: i128) -> Self;
}

macro_rules! impl_int_traits {
	( $( ($type:ty, $is_byte:expr, $is_signed:expr), )* ) => {
		$(
			impl ExtensibleInteger for $type {
                fn is_byte() -> bool { $is_byte }
                fn is_signed() -> bool { $is_signed }

				fn to_u8(&self) -> u8 { *self as u8 }
				fn from_u8(value: u8) -> Self { value as Self }

                fn to_u128(&self) -> u128 { *self as u128 }
				fn from_u128(value: u128) -> Self { value as Self }

                fn to_i128(&self) -> i128 { *self as i128 }
				fn from_i128(value: i128) -> Self { value as Self }
			}
		)*
	};
}

impl_int_traits!(
    (u8, true, false),
    (u16, false, false),
    (u32, false, false),
    (u64, false, false),
    (u128, false, false),
    (usize, false, false),
    (i8, true, true),
    (i16, false, true),
    (i32, false, true),
    (i64, false, true),
    (i128, false, true),
    (isize, false, true),
);

// 1-byte-size Optimisation
// types that are 1 byte large are directly written into a buffer as they are
// when serialized and are just directly returned when parsed

// https://en.wikipedia.org/wiki/LEB128#Encode_signed_32-bit_integer
fn serialize_i128(mut value: i128, serialized: &mut Vec<u8>) {
    loop {
        let byte = value as u8 & 0x7f;
        value >>= 7;
        if (value == 0 && (byte & 0x40) == 0) || (value == -1 && (byte & 0x40) != 0) {
            serialized.push(byte);
            break;
        }
        serialized.push(byte | 0x80);
    }
}

// https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integer
fn serialize_u128(mut value: u128, serialized: &mut Vec<u8>) {
    loop {
        let mut byte = value & 0x7f;
        value >>= 7;
        if value != 0 {
            byte |= 0x80;
        }
        serialized.push(byte as u8);
        if value == 0 {
            break;
        }
    }
}

pub fn serialize<T: ExtensibleInteger>(source: T) -> Vec<u8> {
    let mut serialized = vec![];
    if T::is_byte() {
        serialized.push(source.to_u8());
    } else if T::is_signed() {
        serialize_i128(source.to_i128(), &mut serialized);
    } else {
        serialize_u128(source.to_u128(), &mut serialized);
    }

    serialized
}

macro_rules! get_byte {
    ($bytevec:tt) => {
        unwrap_return!($bytevec.drain(0..1).next())
    };
    ($bytevec:tt, $type:ty) => {
        get_byte!($bytevec) as $type
    };
}

// https://en.wikipedia.org/wiki/LEB128#Decode_signed_32-bit_integer
fn parse_i128(data: &mut Vec<u8>) -> Option<i128> {
    let mut result = 0;
    let mut shift = 0;
    loop {
        let byte = get_byte!(data, i128);
        result |= (byte & 0x7f) << shift;
        shift += 7;
        if 0x80 & byte == 0 {
            if shift < 128 && (byte & 0x40) != 0 {
                result |= !0 << shift;
            }
            break;
        }
    }

    Some(result)
}

// https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integer
fn parse_u128(data: &mut Vec<u8>) -> Option<u128> {
    let mut result = 0;
    let mut shift = 0;

    loop {
        let byte = get_byte!(data, u128);
        result |= (byte & 0x7f) << shift;
        if byte & 0x80 == 0 {
            break;
        }
        shift += 7;
    }

    Some(result)
}

pub fn parse<T: ExtensibleInteger>(data: &mut Vec<u8>) -> Option<T> {
    if T::is_byte() {
        Some(T::from_u8(get_byte!(data)))
    } else if T::is_signed() {
        parse_i128(data).map(T::from_i128)
    } else {
        parse_u128(data).map(T::from_u128)
    }
}