use crate::{
core::{
circuits::boolean::{
boolean_value::{Boolean, BooleanValue},
utils::decoder_circuit,
},
global_value::value::FieldValue,
},
traits::{GetBit, Random, Reveal},
utils::field::BaseField,
};
use core::panic;
use std::ops::{BitAnd, BitAndAssign, BitXor, BitXorAssign, Not};
#[derive(Debug, Clone, Copy)]
pub struct Byte<B: Boolean>([B; 8]);
impl<B: Boolean> Byte<B> {
pub fn new(bits: [B; 8]) -> Self {
Self(bits)
}
pub fn get_bits(&self) -> [B; 8] {
self.0
}
pub fn to_vec(self) -> Vec<B> {
self.0.to_vec()
}
pub fn one_hot_encode(&self) -> [B; 256] {
decoder_circuit(self.to_vec())
.try_into()
.unwrap_or_else(|v: Vec<B>| panic!("Expected a Vec of length 256 (found {})", v.len()))
}
pub fn from_u8_and_bool_val(value: u8, b: B) -> Self {
let bit_true = b;
let bit_false = B::from(false);
Self(
(0u8..8)
.map(|i| {
if (value >> i) & 1u8 == 1u8 {
bit_true
} else {
bit_false
}
})
.collect::<Vec<B>>()
.try_into()
.unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl<B: Boolean> BitAnd for Byte<B> {
type Output = Byte<B>;
fn bitand(self, rhs: Self) -> Self::Output {
Self(
self.get_bits()
.into_iter()
.zip(rhs.get_bits())
.map(|(bit_self, bit_other)| bit_self & bit_other)
.collect::<Vec<B>>()
.try_into()
.unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl<B: Boolean> BitAndAssign for Byte<B> {
fn bitand_assign(&mut self, rhs: Self) {
*self = *self & rhs;
}
}
impl<B: Boolean> BitXor for Byte<B> {
type Output = Byte<B>;
fn bitxor(self, rhs: Self) -> Self::Output {
Self(
self.get_bits()
.into_iter()
.zip(rhs.get_bits())
.map(|(bit_self, bit_other)| bit_self ^ bit_other)
.collect::<Vec<B>>()
.try_into()
.unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl<B: Boolean> BitXorAssign for Byte<B> {
fn bitxor_assign(&mut self, rhs: Self) {
*self = *self ^ rhs;
}
}
impl<B: Boolean> Not for Byte<B> {
type Output = Byte<B>;
fn not(self) -> Self::Output {
Self(
self.get_bits()
.into_iter()
.map(|bit| !bit)
.collect::<Vec<B>>()
.try_into()
.unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl<B: Boolean> Random for Byte<B> {
fn random() -> Self {
Self(
(0..8)
.map(|_| B::random())
.collect::<Vec<B>>()
.try_into()
.unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl<B: Boolean> Reveal for Byte<B> {
fn reveal(self) -> Self {
Self(
self.0
.into_iter()
.map(|bit| bit.reveal())
.collect::<Vec<B>>()
.try_into()
.unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl<B: Boolean> From<u8> for Byte<B> {
fn from(value: u8) -> Self {
Self::from_u8_and_bool_val(value, B::from(true))
}
}
impl From<FieldValue<BaseField>> for Byte<BooleanValue> {
fn from(val: FieldValue<BaseField>) -> Self {
let bounds = val.bounds();
let max = bounds.unsigned_max();
if max.gt(&BaseField::from(255)) {
panic!("bounds must be in [0, 255] (found {:?})", bounds);
}
Self(
(0..8)
.map(|i| val.get_bit(i, false))
.collect::<Vec<BooleanValue>>()
.try_into()
.unwrap_or_else(|v: Vec<BooleanValue>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}),
)
}
}
impl From<Byte<bool>> for u8 {
fn from(value: Byte<bool>) -> Self {
value
.get_bits()
.into_iter()
.enumerate()
.fold(0u8, |acc, (i, b)| if b { acc | (1u8 << i) } else { acc })
}
}