bitcram 0.1.0

A small, derive-based bit packing library for compact integer representations
Documentation
use crate::{Buffer, Packable, Packer, Unpacker};

macro_rules! impl_packable_tuple {
    ($($name:ident),+) => {
        impl<B: Buffer, $($name: Packable<B>),+> Packable<B> for ($($name,)+) {
            const SIZE: u32 = 0 $(+ $name::SIZE)+;

            fn pack(&self) -> B {
                let mut packer = Packer::<B>::new();
                #[allow(non_snake_case)]
                let ($($name,)+) = self;
                $(
                    packer.pack($name);
                )+
                packer.into_inner()
            }

            fn unpack(buffer: B) -> Self {
                let mut unpacker = Unpacker::<B>::new(buffer);
                impl_packable_tuple!(@reverse_unpack unpacker; $($name),+);
                ($($name,)+)
            }
        }
    };

    (@reverse_unpack $unpacker:ident; $name:ident, $($rest:ident),+) => {
        impl_packable_tuple!(@reverse_unpack $unpacker; $($rest),+);
        impl_packable_tuple!(@unpack $unpacker; $name);
    };

    (@reverse_unpack $unpacker:ident; $name:ident) => {
        impl_packable_tuple!(@unpack $unpacker; $name);
    };

    (@unpack $unpacker:ident; $name:ident) => {
        #[allow(non_snake_case)]
        let $name: $name = $unpacker.unpack();
    }
}

macro_rules! impl_packable_tuple_chain {
    ($name:ident, $($rest:ident),+) => {
        impl_packable_tuple!($name, $($rest),+);
        impl_packable_tuple_chain!($($rest),+);
    };
    ($name:ident) => {
        impl_packable_tuple!($name);
    };
}

impl_packable_tuple_chain!(O, P, Q, R, S, T, U, V, W, X, Y, Z);