smolmask 0.1.1

A small library for storing small binary masks in just a single integer.
Documentation
extern crate num;
extern crate num_traits;

use num::{PrimInt, Unsigned};
use num_traits::FromPrimitive;
use std::marker::PhantomData;

pub struct BoolArray<T>
where
    T: PrimInt + Unsigned + FromPrimitive,
{
    phantom: PhantomData<T>,
}

impl<T> BoolArray<T>
where
    T: PrimInt + Unsigned + FromPrimitive,
{
    fn max_size() -> usize {
        std::mem::size_of::<T>() * 4
    }

    pub fn store(bools: &[bool]) -> Result<T, &'static str> {
        let size_shift = Self::max_size() / 2;
        let size = bools.len();
        if size > size_shift {
            return Err("Input length exceeds max size.");
        }

        let mut integer = T::from_usize(size).ok_or("Size conversion failed")? << size_shift;

        for (i, &val) in bools.iter().enumerate() {
            if size_shift - 1 < i {
                return Err("Size shift is less than index, overflow could occur.");
            }
            if val {
                integer = integer | T::one() << (size_shift - 1 - i);
            }
        }

        Ok(integer)
    }

    pub fn retrieve(integer: T) -> Vec<bool> {
        let size_shift = Self::max_size() / 2;
        let size = (integer >> size_shift).to_usize().unwrap();
        let mut bools = vec![false; size];

        for i in 0..size {
            if size_shift - 1 < i {
                panic!("Size shift is less than index, overflow could occur.");
            }
            bools[i] = (integer & (T::one() << (size_shift - 1 - i))) != T::zero();
        }

        bools
    }

    pub fn length(integer: T) -> usize {
        let size_shift = Self::max_size() / 2;
        (integer >> size_shift).to_usize().unwrap()
    }

    pub fn max_bools() -> usize {
        Self::max_size() / 2
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let bools = vec![true, false, true, true];
        let integer = BoolArray::<u64>::store(&bools).unwrap();
        assert_eq!(BoolArray::<u64>::length(integer), bools.len());
        assert_eq!(BoolArray::<u64>::retrieve(integer), bools);
    }

    #[test]
    fn test_error_on_exceed_max_size() {
        let bools = vec![true; BoolArray::<u64>::max_size() / 2 + 1];
        assert!(BoolArray::<u64>::store(&bools).is_err());
    }
}