viewstamped-replication 0.4.0

A Rust-based implementation of the Viewstamped Replication consensus protocol.
Documentation
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::num::NonZeroU128;

#[derive(Copy, Clone, Debug, Default, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct OpNumber(Option<NonZeroU128>);

impl From<u128> for OpNumber {
    fn from(value: u128) -> Self {
        Self(NonZeroU128::new(value))
    }
}

impl From<usize> for OpNumber {
    fn from(value: usize) -> Self {
        Self(NonZeroU128::new(value as u128))
    }
}

impl From<i32> for OpNumber {
    fn from(value: i32) -> Self {
        Self(NonZeroU128::new(value as u128))
    }
}

impl From<OpNumber> for u128 {
    fn from(value: OpNumber) -> Self {
        value.0.map(NonZeroU128::get).unwrap_or(0)
    }
}

impl OpNumber {
    pub fn increment(&mut self) {
        self.0 = NonZeroU128::new(1 + u128::from(*self))
    }

    pub fn next(&self) -> Self {
        Self(NonZeroU128::new(1 + u128::from(*self)))
    }
}

#[derive(Copy, Clone, Debug, Default, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct View(u128);

impl From<u128> for View {
    fn from(value: u128) -> Self {
        Self(value)
    }
}

impl From<View> for u128 {
    fn from(value: View) -> Self {
        value.0
    }
}

impl View {
    pub fn increment(&mut self) {
        self.0 = 1 + self.0;
    }

    pub fn primary_index(&self, group_size: usize) -> usize {
        (self.0 % (group_size as u128)) as usize
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ViewTable {
    table: BTreeMap<View, OpNumber>,
}

impl PartialOrd for ViewTable {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.table.last_key_value().partial_cmp(&other.table.last_key_value())
    }
}

impl Ord for ViewTable {
    fn cmp(&self, other: &Self) -> Ordering {
        self.table.last_key_value().cmp(&other.table.last_key_value())
    }
}

impl ViewTable {
    pub fn insert_view(&mut self, view: View, op_number: OpNumber) {
        self.table.insert(view, op_number);
    }

    pub fn last_entry(&self) -> (View, OpNumber) {
        self.table.last_key_value().map(|kv| (kv.0.clone(), kv.1.clone())).unwrap_or_default()
    }

    pub fn last_op_number(&self) -> OpNumber {
        self.table.last_key_value().map(|kv| kv.1.clone()).unwrap_or_default()
    }
}