small_len 1.1.2

A small library for storing the length in the smallest internal type.
Documentation
#[macro_export]
macro_rules! from_bytes {
    ($($name:ident: $from:ident),*) => {
        $(
            #[inline]
            pub fn $name(raw: Vec<u8>) -> Self {
                let len = raw.len();
                assert!(len != 0, "cannot convert empty bytes to length");

                match len {
                    1 => {
                        let mut bytes = [0; 1];
                        bytes.copy_from_slice(&raw);
                        SmallLength::Byte(u8::$from(bytes))
                    },
                    2 => {
                        let mut bytes = [0; 2];
                        bytes.copy_from_slice(&raw);
                        SmallLength::Word(u16::$from(bytes))
                    },
                    4 => {
                        let mut bytes = [0; 4];
                        bytes.copy_from_slice(&raw);
                        SmallLength::Double(u32::$from(bytes))
                    },
                    8 => {
                        let mut bytes = [0; 8];
                        bytes.copy_from_slice(&raw);
                        SmallLength::Quad(u64::$from(bytes))
                    },
                    _ => panic!("invalid byte length: {}", len),
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! to_bytes {
    ($($name:ident: $to:ident),*) => {
        $(
            #[inline]
            pub fn $name(&self) -> Vec<u8> {
                match self {
                    SmallLength::Byte(v) => {
                        v.$to().to_vec()
                    },
                    SmallLength::Word(v) => {
                        v.$to().to_vec()
                    },
                    SmallLength::Double(v) => {
                        v.$to().to_vec()
                    },
                    SmallLength::Quad(v) => {
                        v.$to().to_vec()
                    },
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! from_length_bytes {
    ($($method:ident: $impl_method:ident),*) => {
        $(
            #[inline]
            pub fn $method(bytes: Vec<u8>) -> Self {
                SmallLength::$impl_method(bytes).into()
            }
        )*
    };
}

#[macro_export]
macro_rules! to_length_bytes {
    ($($method:ident: $impl_method:ident),*) => {
        $(
            #[inline]
            pub fn $method(&self) -> Vec<u8> {
                let s: SmallLength = self.index.into();
                s.$impl_method()
            }
        )*
    };
}

#[macro_export]
macro_rules! length_not_expr {
    ($($type:ident),*) => {
        $(
            impl std::ops::Not for $type {
                type Output = Self;

                #[inline]
                fn not(self) -> Self::Output {
                    (!self.index()).into()
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! length_bin_expr {
    ($type:ident; $($name:ident: $method:ident($op:tt)),*) => {
        $(
            impl $name<$type> for usize {
                type Output = $type;

                #[inline]
                #[deny(arithmetic_overflow)]
                fn $method(self, rhs: $type) -> Self::Output {
                    (self $op rhs.index()).into()
                }
            }

            impl $name<usize> for $type {
                type Output = $type;

                #[inline]
                #[deny(arithmetic_overflow)]
                fn $method(self, rhs: usize) -> Self::Output {
                    (self.index() $op rhs).into()
                }
            }

            impl $name<$type> for $type {
                type Output = $type;

                #[inline]
                #[deny(arithmetic_overflow)]
                fn $method(self, rhs: $type) -> Self::Output {
                    (self.index() $op rhs.index()).into()
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! to_primitive {
    ($($t:ty)*) => {
        $(
            impl From<SmallLength> for $t {

                #[inline]
                fn from(v: SmallLength) -> Self {
                    match v {
                        SmallLength::Byte(v) => {
                            v as $t
                        }
                        SmallLength::Word(v) => {
                            if v <= (<$t>::MAX as u16) {
                                v as $t
                            } else {
                                panic!("word overflow: {} -> {}", v, stringify!($t))
                            }
                        },
                        SmallLength::Double(v) => {
                            if v <= (<$t>::MAX as u32) {
                                v as $t
                            } else {
                                panic!("double overflow: {} -> {}", v, stringify!($t))
                            }
                        },
                        SmallLength::Quad(v) => {
                            if v <= (<$t>::MAX as u64) {
                                v as $t
                            } else {
                                panic!("quad overflow: {} -> {}", v, stringify!($t))
                            }
                        },
                    }
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! impl_len {
    ($($t:ty)*) => {
        $(
            impl Len for $t {
                #[inline]
                fn length(&self) -> Length {
                    self.len().into()
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! impl_len_lifetime {
    ($($t:ty),*) => {
        $(
            impl <'l> Len for $t {
                #[inline]
                fn length(&self) -> Length {
                    self.len().into()
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! impl_len_generic {
    ($($t:ty)*) => {
        $(
            impl <T> Len for $t {
                #[inline]
                fn length(&self) -> Length {
                    self.len().into()
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! impl_len_kv {
    ($($t:ty)*) => {
        $(
            impl <K, V> Len for $t {
                #[inline]
                fn length(&self) -> Length {
                    self.len().into()
                }
            }
        )*
    };
}

#[macro_export]
macro_rules! from_primitive {
    ($($ty:ty { $uty:ty })*) => {
        $(
            impl From<$ty> for SmallLength {
                #[inline]
                fn from(v: $ty) -> Self {
                    if v < 0 {
                        panic!("cannot convert negative value to length")
                    }

                    (v as $uty).into()
                }
            }
        )*
    };
}