proc_bitfield/traits/
arr_impls.rsuse super::{Bit, Bits, SetBit, SetBits, WithBit, WithBits};
macro_rules! impl_bits_for_int_type {
    ($storage: ident ($storage_u: ident), $value: ident ($value_u: ident)) => {
        mod $value {
            use super::*;
            const S_SHIFT: u32 = <$storage>::BITS.trailing_zeros();
            const S_MASK: usize = <$storage>::BITS as usize - 1;
            const V_BITS: usize = <$value>::BITS as usize;
            const V_SHIFT: u32 = <$value>::BITS.trailing_zeros();
            impl<const N: usize> Bits<$value> for [$storage; N] {
                #[inline]
                fn bits<const START: usize, const END: usize>(&self) -> $value {
                    let bits = if START >> S_SHIFT == (END - 1) >> S_SHIFT {
                        (self[START >> S_SHIFT] >> (START & S_MASK)) as $value
                    } else {
                        let mut bits: $value = 0;
                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
                            let start = START.max(i << S_SHIFT);
                            bits |= ((self[i] as $storage_u >> (start & S_MASK)) as $value)
                                << (start - START);
                        }
                        bits
                    };
                    let read_bits = END - START;
                    bits << (V_BITS - read_bits) >> (V_BITS - read_bits)
                }
            }
            impl<const N: usize> WithBits<$value> for [$storage; N] {
                #[inline]
                fn with_bits<const START: usize, const END: usize>(
                    mut self,
                    value: $value,
                ) -> Self {
                    self.set_bits::<START, END>(value);
                    self
                }
            }
            impl<const N: usize> SetBits<$value> for [$storage; N] {
                #[inline]
                fn set_bits<const START: usize, const END: usize>(&mut self, value: $value) {
                    if START >> S_SHIFT == (END - 1) >> S_SHIFT {
                        let i = START >> S_SHIFT;
                        let written_bits = END - START;
                        let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
                            << (START & S_MASK);
                        self[i] =
                            (self[i] & !mask) | ((value as $storage) << (START & S_MASK) & mask);
                    } else {
                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
                            let start = START.max(i << S_SHIFT);
                            let end = END.min((i + 1) << S_SHIFT);
                            let written_bits = end - start;
                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
                                << (start & S_MASK);
                            self[i] = (self[i] & !mask)
                                | (((value >> (start - START)) as $storage) << (start & S_MASK)
                                    & mask);
                        }
                    }
                }
            }
            impl Bits<$value> for [$storage] {
                #[inline]
                fn bits<const START: usize, const END: usize>(&self) -> $value {
                    let bits = if START >> S_SHIFT == (END - 1) >> S_SHIFT {
                        (self[START >> S_SHIFT] >> (START & S_MASK)) as $value
                    } else {
                        let mut bits: $value = 0;
                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
                            let start = START.max(i << S_SHIFT);
                            bits |= ((self[i] as $storage_u >> (start & S_MASK)) as $value)
                                << (start - START);
                        }
                        bits
                    };
                    let read_bits = END - START;
                    bits << (V_BITS - read_bits) >> (V_BITS - read_bits)
                }
            }
            impl SetBits<$value> for [$storage] {
                #[inline]
                fn set_bits<const START: usize, const END: usize>(&mut self, value: $value) {
                    if START >> S_SHIFT == (END - 1) >> S_SHIFT {
                        let i = START >> S_SHIFT;
                        let written_bits = END - START;
                        let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
                            << (START & S_MASK);
                        self[i] =
                            (self[i] & !mask) | ((value as $storage) << (START & S_MASK) & mask);
                    } else {
                        for i in START >> S_SHIFT..=(END - 1) >> S_SHIFT {
                            let start = START.max(i << S_SHIFT);
                            let end = END.min((i + 1) << S_SHIFT);
                            let written_bits = end - start;
                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
                                << (start & S_MASK);
                            self[i] = (self[i] & !mask)
                                | (((value >> (start - START)) as $storage) << (start & S_MASK)
                                    & mask);
                        }
                    }
                }
            }
            impl<const M: usize> Bits<[$value; M]> for $storage {
                #[inline]
                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
                    let mut result = [0; M];
                    for i in 0..=(END - START - 1) >> V_SHIFT {
                        let start = START + (i << V_SHIFT);
                        let end = (start + V_BITS).min(END);
                        let read_bits = end - start;
                        result[i] = ((*self >> start) as $value) << (V_BITS - read_bits)
                            >> (V_BITS - read_bits);
                    }
                    result
                }
            }
            impl<const M: usize> WithBits<[$value; M]> for $storage {
                #[inline]
                fn with_bits<const START: usize, const END: usize>(
                    mut self,
                    value: [$value; M],
                ) -> Self {
                    for i in 0..=(END - START - 1) >> V_SHIFT {
                        let start = START + (i << V_SHIFT);
                        let end = (start + V_BITS).min(END);
                        let written_bits = end - start;
                        let mask =
                            ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1) << start;
                        self = (self & !mask) | ((value[i] as $storage) << start & mask);
                    }
                    self
                }
            }
            impl<const M: usize> SetBits<[$value; M]> for $storage {
                #[inline]
                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
                    *self = self.with_bits::<START, END>(value);
                }
            }
            impl<const M: usize, const N: usize> Bits<[$value; M]> for [$storage; N] {
                #[inline]
                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
                    let mut result = [0; M];
                    for i in 0..=(END - START - 1) >> V_SHIFT {
                        let start = START + (i << V_SHIFT);
                        let end = (start + V_BITS).min(END);
                        let bits = if start >> S_SHIFT == (end - 1) >> S_SHIFT {
                            (self[start >> S_SHIFT] >> (start & S_MASK)) as $value
                        } else {
                            let mut bits: $value = 0;
                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
                                let start_ = start.max(j << S_SHIFT);
                                bits |= ((self[j] as $storage_u >> (start_ & S_MASK)) as $value)
                                    << (start_ - start);
                            }
                            bits
                        };
                        let read_bits = end - start;
                        result[i] = bits << (V_BITS - read_bits) >> (V_BITS - read_bits);
                    }
                    result
                }
            }
            impl<const M: usize, const N: usize> WithBits<[$value; M]> for [$storage; N] {
                #[inline]
                fn with_bits<const START: usize, const END: usize>(
                    mut self,
                    value: [$value; M],
                ) -> Self {
                    self.set_bits::<START, END>(value);
                    self
                }
            }
            impl<const M: usize, const N: usize> SetBits<[$value; M]> for [$storage; N] {
                #[inline]
                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
                    for i in 0..=(END - START - 1) >> V_SHIFT {
                        let start = START + (i << V_SHIFT);
                        let end = (start + V_BITS).min(END);
                        if start >> S_SHIFT == (end - 1) >> S_SHIFT {
                            let j = start >> S_SHIFT;
                            let written_bits = end - start;
                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
                                << (start & S_MASK);
                            self[j] = (self[j] & !mask)
                                | ((value[i] as $storage) << (start & S_MASK) & mask);
                        } else {
                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
                                let start_ = start.max(j << S_SHIFT);
                                let end_ = end.min((j + 1) << S_SHIFT);
                                let written_bits = end_ - start_;
                                let mask = ((1 as $storage) << (written_bits - 1) << 1)
                                    .wrapping_sub(1)
                                    << (start_ & S_MASK);
                                self[j] = (self[j] & !mask)
                                    | (((value[i] >> (start_ - start)) as $storage)
                                        << (start_ & S_MASK)
                                        & mask);
                            }
                        }
                    }
                }
            }
            impl<const M: usize> Bits<[$value; M]> for [$storage] {
                #[inline]
                fn bits<const START: usize, const END: usize>(&self) -> [$value; M] {
                    let mut result = [0; M];
                    for i in 0..=(END - START - 1) >> V_SHIFT {
                        let start = START + (i << V_SHIFT);
                        let end = (start + V_BITS).min(END);
                        let bits = if start >> S_SHIFT == (end - 1) >> S_SHIFT {
                            (self[start >> S_SHIFT] >> (start & S_MASK)) as $value
                        } else {
                            let mut bits: $value = 0;
                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
                                let start_ = start.max(j << S_SHIFT);
                                bits |= ((self[j] as $storage_u >> (start_ & S_MASK)) as $value)
                                    << (start_ - start);
                            }
                            bits
                        };
                        let read_bits = end - start;
                        result[i] = bits << (V_BITS - read_bits) >> (V_BITS - read_bits);
                    }
                    result
                }
            }
            impl<const M: usize> SetBits<[$value; M]> for [$storage] {
                #[inline]
                fn set_bits<const START: usize, const END: usize>(&mut self, value: [$value; M]) {
                    for i in 0..=(END - START - 1) >> V_SHIFT {
                        let start = START + (i << V_SHIFT);
                        let end = (start + V_BITS).min(END);
                        if start >> S_SHIFT == (end - 1) >> S_SHIFT {
                            let j = start >> S_SHIFT;
                            let written_bits = end - start;
                            let mask = ((1 as $storage) << (written_bits - 1) << 1).wrapping_sub(1)
                                << (start & S_MASK);
                            self[j] = (self[j] & !mask)
                                | ((value[i] as $storage) << (start & S_MASK) & mask);
                        } else {
                            for j in start >> S_SHIFT..=(end - 1) >> S_SHIFT {
                                let start_ = start.max(j << S_SHIFT);
                                let end_ = end.min((j + 1) << S_SHIFT);
                                let written_bits = end_ - start_;
                                let mask = ((1 as $storage) << (written_bits - 1) << 1)
                                    .wrapping_sub(1)
                                    << (start_ & S_MASK);
                                self[j] = (self[j] & !mask)
                                    | (((value[i] >> (start_ - start)) as $storage)
                                        << (start_ & S_MASK)
                                        & mask);
                            }
                        }
                    }
                }
            }
        }
    };
}
macro_rules! impl_bits_for_int_types {
    (=> $($dst_ty: ident ($dst_u_ty: ident)),*) => {};
    (
        $src_ty: ident ($src_u_ty: ident)
        $(, $other_src_ty: ident ($other_src_u_ty: ident))*
        => $($dst_ty: ident ($dst_u_ty: ident)),*
    ) => {
        mod $src_ty {
            use super::*;
            $(
                impl_bits_for_int_type!($src_ty ($src_u_ty), $dst_ty ($dst_u_ty));
            )*
        }
        impl_bits_for_int_types!(
            $($other_src_ty ($other_src_u_ty)),* => $($dst_ty ($dst_u_ty)),*
        );
    };
}
mod bits {
    use super::*;
    impl_bits_for_int_types!(
        u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
        i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
            => u8 (u8), u16 (u16), u32 (u32), u64 (u64), u128 (u128), usize (usize),
               i8 (u8), i16 (u16), i32 (u32), i64 (u64), i128 (u128), isize (usize)
    );
}
macro_rules! impl_bit_for_arr_int_type {
    ($t: ident) => {
        mod $t {
            use super::*;
            const SHIFT: u32 = <$t>::BITS.trailing_zeros();
            const MASK: usize = <$t>::BITS as usize - 1;
            impl<const N: usize> Bit for [$t; N] {
                #[inline]
                fn bit<const BIT: usize>(&self) -> bool {
                    self[BIT >> SHIFT] & 1 << (BIT & MASK) != 0
                }
            }
            impl<const N: usize> WithBit for [$t; N] {
                #[inline]
                fn with_bit<const BIT: usize>(mut self, value: bool) -> Self {
                    self.set_bit::<BIT>(value);
                    self
                }
            }
            impl<const N: usize> SetBit for [$t; N] {
                #[inline]
                fn set_bit<const BIT: usize>(&mut self, value: bool) {
                    self[BIT >> SHIFT] =
                        (self[BIT >> SHIFT] & !(1 << (BIT & MASK))) | (value as $t) << BIT;
                }
            }
            impl Bit for [$t] {
                #[inline]
                fn bit<const BIT: usize>(&self) -> bool {
                    self[BIT >> SHIFT] & 1 << (BIT & MASK) != 0
                }
            }
            impl SetBit for [$t] {
                #[inline]
                fn set_bit<const BIT: usize>(&mut self, value: bool) {
                    self[BIT >> SHIFT] =
                        (self[BIT >> SHIFT] & !(1 << (BIT & MASK))) | (value as $t) << BIT;
                }
            }
        }
    };
}
macro_rules! impl_bit_for_arr_int_types {
    ($($t: ident),*) => {
        $(impl_bit_for_arr_int_type!($t);)*
    };
}
mod bit {
    use super::*;
    impl_bit_for_arr_int_types!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
}