pub trait BitField: Sized {
    fn modify_bit(&self, bit: usize, value: bool) -> Self;
    fn set_bit(&mut self, bit: usize, value: bool);
    fn get_bit(&self, bit: usize) -> bool;
}

macro_rules! impl_bit_field {
    ($($ty:ty),+ $(,)?) => {
        $(
            impl BitField for $ty {
                #[inline]
                fn modify_bit(&self, bit: usize, value: bool) -> Self {
                    if value {
                        *self | (1 << bit)
                    } else {
                        *self & !(1 << bit)
                    }
                }

                #[inline]
                fn set_bit(&mut self, bit: usize, value: bool) {
                    *self = self.modify_bit(bit, value);
                }

                #[inline]
                fn get_bit(&self, bit: usize) -> bool {
                    *self & (1 << bit) != 0
                }
            }
        )+
    };
}

impl_bit_field!(u8, u16, u32, u64, usize);
impl_bit_field!(i8, i16, i32, i64, isize);
