use crate::crypto::{GeneratesRandom, RandomGenerator};
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use zeroize::DefaultIsZeroes;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(transparent)]
pub struct Party {
index: u8,
}
impl DefaultIsZeroes for Party {}
impl Party {
pub fn index(&self) -> usize {
return self.index as usize;
}
pub fn next(self) -> Self {
return Party {
index: (self.index + 1) % 3,
};
}
}
impl From<u8> for Party {
fn from(index: u8) -> Self {
return Party { index: index % 3 };
}
}
impl From<usize> for Party {
fn from(index: usize) -> Self {
return Party {
index: (index % 3) as u8,
};
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct PartyVec {
bytes: Vec<u8>,
len: usize,
}
impl PartyVec {
pub fn new() -> Self {
return Self {
bytes: Vec::new(),
len: 0,
};
}
pub fn with_capacity(capacity: usize) -> Self {
return Self {
bytes: Vec::with_capacity((capacity + 3) / 4),
len: 0,
};
}
pub fn push(&mut self, party: Party) {
let vec = &mut self.bytes;
if self.len % 4 == 0 {
vec.push(0u8);
}
let (byte_idx, shift) = Self::byte_idx_and_shift(self.len);
vec[byte_idx] |= party.index << shift;
self.len += 1;
}
pub fn get(&self, index: usize) -> Option<Party> {
if index >= self.len {
return None;
}
let (byte_idx, shift) = Self::byte_idx_and_shift(index);
let idx = (self.bytes[byte_idx] >> shift) & 0b11;
return Some(Party { index: idx });
}
pub fn len(&self) -> usize {
return self.len;
}
pub fn byte_idx_and_shift(index: usize) -> (usize, u8) {
let byte_idx = index / 4;
let bitpair_idx = (index % 4) as u8;
let shift = 2u8 * (3u8 - bitpair_idx);
return (byte_idx, shift);
}
}
#[derive(Debug)]
pub struct PartyIter<'a> {
vec: &'a PartyVec,
pos: usize,
}
impl<'a> Iterator for PartyIter<'a> {
type Item = Party;
fn next(&mut self) -> Option<Party> {
if self.pos >= self.vec.len {
return None;
}
let (byte_idx, shift) = PartyVec::byte_idx_and_shift(self.pos);
let idx: u8 = (self.vec.bytes[byte_idx] >> shift) & 0b11;
self.pos += 1;
return Some(Party { index: idx });
}
}
impl<'a> IntoIterator for &'a PartyVec {
type Item = Party;
type IntoIter = PartyIter<'a>;
fn into_iter(self) -> Self::IntoIter {
return PartyIter { vec: self, pos: 0 };
}
}
#[derive(Debug)]
pub struct ChallengeGenerator<R: RandomGenerator> {
generator: R,
current_byte: u8,
bits_used: u8,
}
impl<R: RandomGenerator> ChallengeGenerator<R> {
pub fn new(generator: R) -> Self {
return ChallengeGenerator {
generator,
current_byte: 0,
bits_used: 8, };
}
}
impl<R: RandomGenerator> GeneratesRandom<Party> for ChallengeGenerator<R> {
fn next(&mut self) -> Party {
let mut party: u8 = 0b11; while party > 2 {
if self.bits_used == 8 {
self.current_byte = self.generator.next_byte();
self.bits_used = 0;
}
party = self.current_byte & 0b11;
self.current_byte >>= 2;
self.bits_used += 2;
}
return party.into();
}
}