use const_num_traits::{ConstOne, ConstZero, PrimBits};
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
#[derive(Copy, Clone, Debug)]
struct CtWord(u32);
impl Not for CtWord {
type Output = Self;
fn not(self) -> Self {
CtWord(!self.0)
}
}
impl BitAnd for CtWord {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
CtWord(self.0 & rhs.0)
}
}
impl BitOr for CtWord {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
CtWord(self.0 | rhs.0)
}
}
impl BitXor for CtWord {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
CtWord(self.0 ^ rhs.0)
}
}
impl Shl<usize> for CtWord {
type Output = Self;
fn shl(self, n: usize) -> Self {
CtWord(self.0 << n)
}
}
impl Shr<usize> for CtWord {
type Output = Self;
fn shr(self, n: usize) -> Self {
CtWord(self.0 >> n)
}
}
impl ConstZero for CtWord {
const ZERO: Self = CtWord(0);
}
impl ConstOne for CtWord {
const ONE: Self = CtWord(1);
}
impl PrimBits for CtWord {
fn count_ones(self) -> u32 {
self.0.count_ones()
}
fn count_zeros(self) -> u32 {
self.0.count_zeros()
}
fn leading_zeros(self) -> u32 {
self.0.leading_zeros()
}
fn trailing_zeros(self) -> u32 {
self.0.trailing_zeros()
}
fn rotate_left(self, n: u32) -> Self {
CtWord(self.0.rotate_left(n))
}
fn rotate_right(self, n: u32) -> Self {
CtWord(self.0.rotate_right(n))
}
fn signed_shl(self, n: u32) -> Self {
CtWord(((self.0 as i32) << n) as u32)
}
fn signed_shr(self, n: u32) -> Self {
CtWord(((self.0 as i32) >> n) as u32)
}
fn unsigned_shl(self, n: u32) -> Self {
CtWord(self.0 << n)
}
fn unsigned_shr(self, n: u32) -> Self {
CtWord(self.0 >> n)
}
fn swap_bytes(self) -> Self {
CtWord(self.0.swap_bytes())
}
fn from_be(x: Self) -> Self {
CtWord(u32::from_be(x.0))
}
fn from_le(x: Self) -> Self {
CtWord(u32::from_le(x.0))
}
fn to_be(self) -> Self {
CtWord(self.0.to_be())
}
fn to_le(self) -> Self {
CtWord(self.0.to_le())
}
}
fn parity_of_reversed<T: PrimBits>(x: T) -> u32 {
x.reverse_bits().count_ones() & 1
}
#[test]
fn ct_word_implements_prim_bits() {
let x = CtWord(0x12345678);
assert_eq!(x.count_ones(), 13);
assert_eq!(x.leading_zeros(), 3);
assert_eq!(CtWord(0xF000_0001).leading_ones(), 4);
assert_eq!(CtWord(0xF000_0001).trailing_ones(), 1);
assert_eq!(x.reverse_bits().0, 0x12345678u32.reverse_bits());
assert_eq!(parity_of_reversed(x), 13 & 1);
assert_eq!(parity_of_reversed(0x12345678u32), 13 & 1);
}