use std::fmt;
use std::num::NonZeroU64;
use serde::{Deserialize, Serialize};
use crate::account::model::{Modseq, Uid};
#[derive(
Deserialize,
Serialize,
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
)]
#[serde(transparent)]
pub struct Cid(pub u32);
impl Cid {
pub const GENESIS: Self = Cid(0);
pub const MIN: Self = Cid(1);
pub const END: Self = Cid(4_000_000_000);
pub const MAX: Self = Cid(Cid::END.0 - 1);
pub fn next(self) -> Option<Self> {
if self < Cid::MAX {
Some(Cid(self.0 + 1))
} else {
None
}
}
}
#[derive(
Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[serde(transparent)]
pub struct V1Modseq(NonZeroU64);
impl V1Modseq {
pub const MIN: Self = Self(NonZeroU64::new(Cid::END.0 as u64).unwrap());
pub fn of(raw: u64) -> Option<Self> {
NonZeroU64::new(raw).map(Self).filter(|&m| m >= Self::MIN)
}
pub fn import(modseq: Modseq) -> Option<Self> {
Self::of(modseq.raw())
}
pub fn new(uid: Uid, cid: Cid) -> Self {
Self(
NonZeroU64::new(
(uid.0.get() as u64) * (Cid::END.0 as u64) + cid.0 as u64,
)
.unwrap(),
)
}
pub fn raw(self) -> NonZeroU64 {
self.0
}
pub fn uid(self) -> Uid {
Uid::of((self.0.get() / (Cid::END.0 as u64)) as u32).unwrap()
}
pub fn cid(self) -> Cid {
Cid((self.0.get() % (Cid::END.0 as u64)) as u32)
}
pub fn combine(self, other: Self) -> Self {
Self::new(self.uid().max(other.uid()), self.cid().max(other.cid()))
}
pub fn with_uid(self, uid: Uid) -> Self {
Self::new(uid, self.cid())
}
pub fn with_cid(self, cid: Cid) -> Self {
Self::new(self.uid(), cid)
}
pub fn next(self) -> Option<Self> {
self.cid().next().map(|cid| self.with_cid(cid))
}
}
impl fmt::Debug for V1Modseq {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Modseq({}:{}={})",
self.uid().0.get(),
self.cid().0,
self.0.get()
)
}
}
impl From<V1Modseq> for Modseq {
fn from(m: V1Modseq) -> Self {
Self::of(m.raw().get())
}
}
impl From<Option<V1Modseq>> for Modseq {
fn from(m: Option<V1Modseq>) -> Self {
Self::of(m.map(|m| m.raw().get()).unwrap_or(1))
}
}