use std::{
fmt::{Debug, Display},
ops::{Add, BitAnd, Not, Sub},
};
pub trait Unsigned:
Add<Output = Self>
+ Sub<Output = Self>
+ BitAnd<Output = Self>
+ Not<Output = Self>
+ Sized
+ From<u8>
+ Eq
+ Debug
+ Display
+ Clone
+ Copy
{
}
impl<
U: Add<Output = Self>
+ Sub<Output = Self>
+ BitAnd<Output = Self>
+ Not<Output = Self>
+ Sized
+ From<u8>
+ Eq
+ Debug
+ Display
+ Clone
+ Copy,
> Unsigned for U
{
}
#[inline(always)]
pub fn is_pow2<U: Unsigned>(v: U) -> bool {
v & (v - U::from(1)) == U::from(0)
}
#[inline(always)]
pub fn assert_pow2<U: Unsigned>(v: U) {
assert_eq!(v & (v - U::from(1)), U::from(0), "v: {v}");
}
#[inline(always)]
pub fn debug_assert_pow2<U: Unsigned>(v: U) {
debug_assert_eq!(v & (v - U::from(1)), U::from(0), "v: {v}");
}
#[inline(always)]
pub fn is_aligned<U: Unsigned>(align: U, v: U) -> bool {
debug_assert_pow2(align);
v & (align - U::from(1)) == U::from(0)
}
#[inline(always)]
pub fn assert_aligned<U: Unsigned>(align: U, v: U) {
debug_assert_pow2(align);
assert!(is_aligned(align, v), "align: {align}, v: {v}");
}
#[inline(always)]
pub fn debug_assert_aligned<U: Unsigned>(align: U, v: U) {
debug_assert_pow2(align);
debug_assert!(is_aligned(align, v), "align: {align}, v: {v}");
}
#[inline(always)]
pub fn align_up<U: Unsigned>(align: U, v: U) -> U {
debug_assert_pow2(align);
(v + align - U::from(1)) & !(align - U::from(1))
}
#[inline(always)]
pub fn align_down<U: Unsigned>(align: U, v: U) -> U {
debug_assert_pow2(align);
v & !(align - U::from(1))
}