use core::cmp::Ordering;
use crate::{DeletionTs, Length, ReplicaId, ReplicaIdMap};
pub type DeletionMap = BaseMap<DeletionTs>;
pub type VersionMap = BaseMap<Length>;
#[derive(Clone, PartialEq, Eq)]
pub struct BaseMap<T> {
this_id: ReplicaId,
this_value: T,
rest: ReplicaIdMap<T>,
}
impl<T: Copy> BaseMap<T> {
#[inline]
pub fn get(&self, replica_id: ReplicaId) -> T
where
T: Default,
{
if replica_id == self.this_id {
self.this_value
} else {
self.rest.get(&replica_id).copied().unwrap_or_default()
}
}
#[inline]
pub fn get_mut(&mut self, replica_id: ReplicaId) -> &mut T
where
T: Default,
{
if replica_id == self.this_id {
&mut self.this_value
} else {
self.rest.entry(replica_id).or_default()
}
}
#[inline]
pub fn fork(&self, new_id: ReplicaId, restart_at: T) -> Self {
let mut forked = self.clone();
forked.fork_in_place(new_id, restart_at);
forked
}
#[inline]
pub fn fork_in_place(&mut self, new_id: ReplicaId, restart_at: T) {
self.rest.insert(self.this_id, self.this_value);
self.this_id = new_id;
self.this_value = restart_at;
}
#[inline]
pub fn insert(&mut self, replica_id: ReplicaId, value: T) {
if replica_id != self.this_id {
self.rest.insert(replica_id, value);
}
}
#[inline]
fn iter(&self) -> impl Iterator<Item = (ReplicaId, T)> + '_ {
let this_entry = core::iter::once((self.this_id, self.this_value));
this_entry.chain(self.rest.iter().map(|(&id, &value)| (id, value)))
}
#[inline]
pub(crate) fn iter_mut(
&mut self,
) -> impl Iterator<Item = (ReplicaId, &mut T)> + '_ {
let this_entry =
core::iter::once((self.this_id, &mut self.this_value));
this_entry.chain(self.rest.iter_mut().map(|(&id, value)| (id, value)))
}
#[inline]
pub fn new(this_id: ReplicaId, this_value: T) -> Self {
Self { this_id, this_value, rest: ReplicaIdMap::default() }
}
#[inline]
pub fn this(&self) -> T {
self.this_value
}
#[inline]
pub fn this_id(&self) -> ReplicaId {
self.this_id
}
#[inline]
pub fn this_mut(&mut self) -> &mut T {
&mut self.this_value
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for BaseMap<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let this_entry = core::iter::once((&self.this_id, &self.this_value));
f.debug_map().entries(this_entry.chain(self.rest.iter())).finish()
}
}
impl PartialOrd for VersionMap {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
#[inline]
fn update_order<I>(iter: I, mut order: Ordering) -> Option<Ordering>
where
I: Iterator<Item = (Length, Length)>,
{
for (this_value, other_value) in iter {
match this_value.cmp(&other_value) {
Ordering::Greater => {
if order == Ordering::Less {
return None;
}
order = Ordering::Greater;
},
Ordering::Less => {
if order == Ordering::Greater {
return None;
}
order = Ordering::Less;
},
Ordering::Equal => {},
}
}
Some(order)
}
let mut order = Ordering::Equal;
let iter = self.iter().filter(|(_, value)| *value > 0).map(
|(this_id, this_value)| {
let other_value = other.get(this_id);
(this_value, other_value)
},
);
order = update_order(iter, order)?;
let iter = other.iter().filter(|(_, value)| *value > 0).map(
|(other_id, other_value)| {
let this_value = self.get(other_id);
(this_value, other_value)
},
);
update_order(iter, order)
}
}
#[cfg(feature = "encode")]
pub(crate) mod encode {
use super::*;
use crate::encode::{Decode, Encode, IntDecodeError};
impl<T: Encode> Encode for BaseMap<T> {
#[inline]
fn encode(&self, buf: &mut Vec<u8>) {
self.this_id.encode(buf);
self.this_value.encode(buf);
(self.rest.len() as u64).encode(buf);
for (id, value) in self.rest.iter() {
id.encode(buf);
value.encode(buf);
}
}
}
pub(crate) enum BaseMapDecodeError<T: Decode> {
Key(IntDecodeError),
Value(T::Error),
}
impl<T: Decode> From<IntDecodeError> for BaseMapDecodeError<T> {
#[inline(always)]
fn from(err: IntDecodeError) -> Self {
Self::Key(err)
}
}
impl<T: Decode> core::fmt::Display for BaseMapDecodeError<T> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let err: &dyn core::fmt::Display = match self {
Self::Key(err) => err,
Self::Value(err) => err,
};
write!(
f,
"BaseMap<{:?}>: couldn't be decoded: {err}",
core::any::type_name::<T>()
)
}
}
impl<T: Decode<Value = T>> Decode for BaseMap<T> {
type Value = Self;
type Error = BaseMapDecodeError<T>;
#[inline]
fn decode(buf: &[u8]) -> Result<(Self::Value, &[u8]), Self::Error> {
let (this_id, buf) = ReplicaId::decode(buf)?;
let (this_value, buf) =
T::decode(buf).map_err(BaseMapDecodeError::Value)?;
let (rest_len, mut buf) = u64::decode(buf)?;
let mut rest = ReplicaIdMap::default();
for _ in 0..rest_len {
let (id, new_buf) = ReplicaId::decode(buf)?;
let (value, new_buf) =
T::decode(new_buf).map_err(BaseMapDecodeError::Value)?;
rest.insert(id, value);
buf = new_buf;
}
let this = Self { this_id, this_value, rest };
Ok((this, buf))
}
}
}
#[cfg(feature = "serde")]
mod serde {
crate::encode::impl_serialize!(super::DeletionMap);
crate::encode::impl_deserialize!(super::DeletionMap);
crate::encode::impl_serialize!(super::VersionMap);
crate::encode::impl_deserialize!(super::VersionMap);
}