use std::ops::{Index, IndexMut};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum VoterIndex {
First,
Second,
Third,
}
impl VoterIndex {
pub(crate) const ALL: [Self; 3] = [Self::First, Self::Second, Self::Third];
pub(crate) const fn primary(view: u64) -> Self {
match view % 3 {
0 => Self::First,
1 => Self::Second,
_ => Self::Third,
}
}
pub(crate) const fn others(self) -> [Self; 2] {
match self {
Self::First => [Self::Second, Self::Third],
Self::Second => [Self::Third, Self::First],
Self::Third => [Self::First, Self::Second],
}
}
const fn bit(self) -> u8 {
match self {
Self::First => 1,
Self::Second => 2,
Self::Third => 4,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct Voters<T>(pub(crate) [T; 3]);
impl<T: Copy> Voters<T> {
pub(crate) const fn splat(value: T) -> Self {
Self([value; 3])
}
}
impl<T> Voters<T> {
pub(crate) fn values(&self) -> std::slice::Iter<'_, T> {
self.0.iter()
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (VoterIndex, &T)> {
VoterIndex::ALL.into_iter().zip(&self.0)
}
}
impl<T> Index<VoterIndex> for Voters<T> {
type Output = T;
fn index(&self, voter: VoterIndex) -> &T {
let [first, second, third] = &self.0;
match voter {
VoterIndex::First => first,
VoterIndex::Second => second,
VoterIndex::Third => third,
}
}
}
impl<T> IndexMut<VoterIndex> for Voters<T> {
fn index_mut(&mut self, voter: VoterIndex) -> &mut T {
let [first, second, third] = &mut self.0;
match voter {
VoterIndex::First => first,
VoterIndex::Second => second,
VoterIndex::Third => third,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) struct VoterSet(u8);
impl VoterSet {
pub(crate) const EMPTY: Self = Self(0);
pub(crate) const fn mask(self) -> u8 {
self.0
}
pub(crate) const fn contains(self, voter: VoterIndex) -> bool {
self.0 & voter.bit() != 0
}
pub(crate) const fn len(self) -> u32 {
self.0.count_ones()
}
pub(crate) const fn is_empty(self) -> bool {
self.0 == 0
}
pub(crate) fn insert(&mut self, voter: VoterIndex) {
self.0 |= voter.bit();
}
pub(crate) fn remove(&mut self, voter: VoterIndex) {
self.0 &= !voter.bit();
}
pub(crate) fn pop_first(&mut self) -> Option<VoterIndex> {
let voter = VoterIndex::ALL
.into_iter()
.find(|&voter| self.contains(voter))?;
self.remove(voter);
Some(voter)
}
}
impl FromIterator<VoterIndex> for VoterSet {
fn from_iter<I: IntoIterator<Item = VoterIndex>>(voters: I) -> Self {
let mut set = Self::EMPTY;
voters.into_iter().for_each(|voter| set.insert(voter));
set
}
}