use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Id {
Zero,
One,
Branch(Box<Self>, Box<Self>),
}
impl Id {
#[must_use]
pub const fn zero() -> Self {
Self::Zero
}
#[must_use]
pub const fn one() -> Self {
Self::One
}
#[must_use]
pub fn branch(left: Self, right: Self) -> Self {
match (&left, &right) {
(Self::Zero, Self::Zero) => Self::Zero,
(Self::One, Self::One) => Self::One,
_ => Self::Branch(Box::new(left), Box::new(right)),
}
}
#[must_use]
pub fn is_zero(&self) -> bool {
*self == Self::Zero
}
#[must_use]
pub fn is_one(&self) -> bool {
*self == Self::One
}
#[must_use]
pub const fn is_leaf(&self) -> bool {
matches!(self, Self::Zero | Self::One)
}
#[must_use]
pub const fn is_branch(&self) -> bool {
matches!(self, Self::Branch(..))
}
#[must_use]
pub fn depth(&self) -> usize {
match self {
Self::Zero | Self::One => 0,
Self::Branch(l, r) => 1 + l.depth().max(r.depth()),
}
}
#[must_use]
pub fn node_count(&self) -> usize {
match self {
Self::Zero | Self::One => 1,
Self::Branch(l, r) => 1 + l.node_count() + r.node_count(),
}
}
#[must_use]
pub fn normalize(self) -> Self {
match self {
Self::Zero | Self::One => self,
Self::Branch(l, r) => {
let nl = l.normalize();
let nr = r.normalize();
Self::branch(nl, nr)
}
}
}
}
impl fmt::Debug for Id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Zero => write!(f, "0"),
Self::One => write!(f, "1"),
Self::Branch(l, r) => write!(f, "({l:?}, {r:?})"),
}
}
}
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Event {
Leaf(u32),
Branch(u32, Box<Self>, Box<Self>),
}
impl Event {
#[must_use]
pub const fn leaf(value: u32) -> Self {
Self::Leaf(value)
}
#[must_use]
pub const fn zero() -> Self {
Self::Leaf(0)
}
#[must_use]
pub fn branch(base: u32, left: Self, right: Self) -> Self {
match (&left, &right) {
(Self::Leaf(a), Self::Leaf(b)) if a == b => Self::Leaf(base + a),
_ => {
let min_val = left.min_value().min(right.min_value());
if min_val > 0 {
Self::Branch(
base + min_val,
Box::new(left.subtract_base(min_val)),
Box::new(right.subtract_base(min_val)),
)
} else {
Self::Branch(base, Box::new(left), Box::new(right))
}
}
}
}
#[must_use]
pub const fn is_leaf(&self) -> bool {
matches!(self, Self::Leaf(_))
}
#[must_use]
pub const fn is_branch(&self) -> bool {
matches!(self, Self::Branch(..))
}
#[must_use]
pub const fn value(&self) -> u32 {
match self {
Self::Leaf(n) | Self::Branch(n, _, _) => *n,
}
}
#[must_use]
pub fn min_value(&self) -> u32 {
match self {
Self::Leaf(n) => *n,
Self::Branch(n, l, r) => n + l.min_value().min(r.min_value()),
}
}
#[must_use]
pub fn max_value(&self) -> u32 {
match self {
Self::Leaf(n) => *n,
Self::Branch(n, l, r) => n + l.max_value().max(r.max_value()),
}
}
#[must_use]
pub fn depth(&self) -> usize {
match self {
Self::Leaf(_) => 0,
Self::Branch(_, l, r) => 1 + l.depth().max(r.depth()),
}
}
#[must_use]
pub fn node_count(&self) -> usize {
match self {
Self::Leaf(_) => 1,
Self::Branch(_, l, r) => 1 + l.node_count() + r.node_count(),
}
}
#[must_use]
pub fn normalize(self) -> Self {
match self {
Self::Leaf(_) => self,
Self::Branch(n, l, r) => {
let nl = l.normalize();
let nr = r.normalize();
Self::branch(n, nl, nr)
}
}
}
#[must_use]
pub fn lift(self, delta: u32) -> Self {
match self {
Self::Leaf(n) => Self::Leaf(n + delta),
Self::Branch(n, l, r) => Self::Branch(n + delta, l, r),
}
}
#[must_use]
fn subtract_base(self, delta: u32) -> Self {
match self {
Self::Leaf(n) => {
assert!(delta <= n, "subtract_base: delta {delta} > leaf value {n}");
Self::Leaf(n - delta)
}
Self::Branch(n, l, r) => {
assert!(delta <= n, "subtract_base: delta {delta} > branch base {n}");
Self::Branch(n - delta, l, r)
}
}
}
}
impl fmt::Debug for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Leaf(n) => write!(f, "{n}"),
Self::Branch(n, l, r) => write!(f, "({n}, {l:?}, {r:?})"),
}
}
}
impl fmt::Display for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Stamp {
pub id: Id,
pub event: Event,
}
impl Stamp {
#[must_use]
pub const fn new(id: Id, event: Event) -> Self {
Self { id, event }
}
#[must_use]
pub const fn seed() -> Self {
Self {
id: Id::one(),
event: Event::zero(),
}
}
#[must_use]
pub const fn anonymous() -> Self {
Self {
id: Id::zero(),
event: Event::zero(),
}
}
#[must_use]
pub fn is_anonymous(&self) -> bool {
self.id.is_zero()
}
#[must_use]
pub fn normalize(self) -> Self {
Self {
id: self.id.normalize(),
event: self.event.normalize(),
}
}
}
impl fmt::Display for Stamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.id, self.event)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_id_zero() {
let id = Id::zero();
assert!(id.is_zero());
assert!(!id.is_one());
assert!(id.is_leaf());
assert!(!id.is_branch());
assert_eq!(id.depth(), 0);
assert_eq!(id.node_count(), 1);
}
#[test]
fn test_id_one() {
let id = Id::one();
assert!(!id.is_zero());
assert!(id.is_one());
assert!(id.is_leaf());
assert!(!id.is_branch());
assert_eq!(id.depth(), 0);
assert_eq!(id.node_count(), 1);
}
#[test]
fn test_id_branch_distinct_children() {
let id = Id::branch(Id::one(), Id::zero());
assert!(!id.is_zero());
assert!(!id.is_one());
assert!(!id.is_leaf());
assert!(id.is_branch());
assert_eq!(id.depth(), 1);
assert_eq!(id.node_count(), 3);
}
#[test]
fn test_id_branch_both_zero_normalizes() {
let id = Id::branch(Id::zero(), Id::zero());
assert_eq!(id, Id::Zero);
assert!(id.is_zero());
}
#[test]
fn test_id_branch_both_one_normalizes() {
let id = Id::branch(Id::one(), Id::one());
assert_eq!(id, Id::One);
assert!(id.is_one());
}
#[test]
fn test_id_nested_normalization() {
let id = Id::branch(
Id::branch(Id::zero(), Id::zero()),
Id::branch(Id::one(), Id::one()),
);
assert_eq!(id, Id::branch(Id::zero(), Id::one()));
}
#[test]
fn test_id_deep_normalization() {
let inner = Id::branch(Id::one(), Id::one()); let mid = Id::branch(inner.clone(), inner); let outer = Id::branch(mid.clone(), mid); assert_eq!(outer, Id::One);
}
#[test]
fn test_id_normalize_method() {
let id = Id::Branch(
Box::new(Id::Branch(Box::new(Id::Zero), Box::new(Id::Zero))),
Box::new(Id::One),
);
let normalized = id.normalize();
assert_eq!(normalized, Id::branch(Id::zero(), Id::one()));
}
#[test]
fn test_id_normalize_already_minimal() {
let id = Id::branch(Id::one(), Id::zero());
let normalized = id.clone().normalize();
assert_eq!(id, normalized);
}
#[test]
fn test_id_display_zero() {
assert_eq!(format!("{}", Id::zero()), "0");
}
#[test]
fn test_id_display_one() {
assert_eq!(format!("{}", Id::one()), "1");
}
#[test]
fn test_id_display_branch() {
let id = Id::branch(Id::one(), Id::zero());
assert_eq!(format!("{id}"), "(1, 0)");
}
#[test]
fn test_id_display_nested() {
let id = Id::branch(Id::branch(Id::one(), Id::zero()), Id::zero());
assert_eq!(format!("{id}"), "((1, 0), 0)");
}
#[test]
fn test_id_equality() {
assert_eq!(Id::zero(), Id::zero());
assert_eq!(Id::one(), Id::one());
assert_ne!(Id::zero(), Id::one());
let a = Id::branch(Id::one(), Id::zero());
let b = Id::branch(Id::one(), Id::zero());
assert_eq!(a, b);
let c = Id::branch(Id::zero(), Id::one());
assert_ne!(a, c);
}
#[test]
fn test_id_clone() {
let id = Id::branch(Id::one(), Id::branch(Id::zero(), Id::one()));
let cloned = id.clone();
assert_eq!(id, cloned);
}
#[test]
fn test_id_represents_left_half_partition() {
let id = Id::branch(Id::one(), Id::zero());
assert!(!id.is_zero());
assert!(!id.is_one());
assert_eq!(id.depth(), 1);
}
#[test]
fn test_id_represents_quarter_partition() {
let id = Id::branch(Id::branch(Id::one(), Id::zero()), Id::zero());
assert_eq!(id.depth(), 2);
assert_eq!(id.node_count(), 5);
}
#[test]
fn test_event_zero() {
let e = Event::zero();
assert!(e.is_leaf());
assert!(!e.is_branch());
assert_eq!(e.value(), 0);
assert_eq!(e.min_value(), 0);
assert_eq!(e.max_value(), 0);
assert_eq!(e.depth(), 0);
assert_eq!(e.node_count(), 1);
}
#[test]
fn test_event_leaf() {
let e = Event::leaf(5);
assert!(e.is_leaf());
assert_eq!(e.value(), 5);
assert_eq!(e.min_value(), 5);
assert_eq!(e.max_value(), 5);
}
#[test]
fn test_event_branch_distinct_children() {
let e = Event::branch(1, Event::leaf(2), Event::leaf(3));
assert!(e.is_branch());
assert_eq!(e.value(), 3); assert_eq!(e.min_value(), 3); assert_eq!(e.max_value(), 4); }
#[test]
fn test_event_branch_equal_leaves_normalizes() {
let e = Event::branch(2, Event::leaf(3), Event::leaf(3));
assert_eq!(e, Event::Leaf(5));
}
#[test]
fn test_event_branch_zero_leaves_normalizes() {
let e = Event::branch(0, Event::leaf(0), Event::leaf(0));
assert_eq!(e, Event::Leaf(0));
}
#[test]
fn test_event_branch_lifts_common_minimum() {
let e = Event::branch(0, Event::leaf(3), Event::leaf(5));
assert_eq!(
e,
Event::Branch(3, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
);
}
#[test]
fn test_event_branch_base_plus_lift() {
let e = Event::branch(2, Event::leaf(3), Event::leaf(5));
assert_eq!(
e,
Event::Branch(5, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
);
}
#[test]
fn test_event_branch_one_child_zero_no_lift() {
let e = Event::branch(0, Event::leaf(0), Event::leaf(3));
assert_eq!(
e,
Event::Branch(0, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(3)))
);
}
#[test]
fn test_event_normalize_method() {
let e = Event::Branch(
0,
Box::new(Event::Branch(
0,
Box::new(Event::Leaf(2)),
Box::new(Event::Leaf(2)),
)),
Box::new(Event::Leaf(2)),
);
let normalized = e.normalize();
assert_eq!(normalized, Event::Leaf(2));
}
#[test]
fn test_event_normalize_partial_collapse() {
let e = Event::Branch(
0,
Box::new(Event::Branch(
0,
Box::new(Event::Leaf(1)),
Box::new(Event::Leaf(1)),
)),
Box::new(Event::Leaf(3)),
);
let normalized = e.normalize();
assert_eq!(
normalized,
Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
);
}
#[test]
fn test_event_min_value_branch() {
let e = Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3)));
assert_eq!(e.min_value(), 3);
}
#[test]
fn test_event_max_value_branch() {
let e = Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3)));
assert_eq!(e.max_value(), 5);
}
#[test]
fn test_event_min_max_deep() {
let e = Event::Branch(
1,
Box::new(Event::Branch(
2,
Box::new(Event::Leaf(0)),
Box::new(Event::Leaf(3)),
)),
Box::new(Event::Leaf(1)),
);
assert_eq!(e.min_value(), 2);
assert_eq!(e.max_value(), 6);
}
#[test]
fn test_event_lift_leaf() {
let e = Event::leaf(3).lift(2);
assert_eq!(e, Event::Leaf(5));
}
#[test]
fn test_event_lift_branch() {
let e = Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)));
let lifted = e.lift(3);
assert_eq!(
lifted,
Event::Branch(4, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
);
}
#[test]
fn test_event_lift_zero() {
let e = Event::leaf(5);
let lifted = e.lift(0);
assert_eq!(lifted, Event::Leaf(5));
}
#[test]
fn test_event_display_leaf() {
assert_eq!(format!("{}", Event::leaf(7)), "7");
}
#[test]
fn test_event_display_branch() {
let e = Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)));
assert_eq!(format!("{e}"), "(1, 0, 2)");
}
#[test]
fn test_event_equality() {
assert_eq!(Event::zero(), Event::zero());
assert_eq!(Event::leaf(3), Event::leaf(3));
assert_ne!(Event::leaf(3), Event::leaf(4));
}
#[test]
fn test_event_clone() {
let e = Event::Branch(
1,
Box::new(Event::Branch(
0,
Box::new(Event::Leaf(1)),
Box::new(Event::Leaf(2)),
)),
Box::new(Event::Leaf(3)),
);
let cloned = e.clone();
assert_eq!(e, cloned);
}
#[test]
fn test_event_depth_nested() {
let e = Event::Branch(
0,
Box::new(Event::Branch(
0,
Box::new(Event::Leaf(0)),
Box::new(Event::Leaf(1)),
)),
Box::new(Event::Leaf(0)),
);
assert_eq!(e.depth(), 2);
}
#[test]
fn test_event_node_count_nested() {
let e = Event::Branch(
0,
Box::new(Event::Branch(
0,
Box::new(Event::Leaf(0)),
Box::new(Event::Leaf(1)),
)),
Box::new(Event::Leaf(0)),
);
assert_eq!(e.node_count(), 5);
}
#[test]
fn test_stamp_seed() {
let s = Stamp::seed();
assert_eq!(s.id, Id::One);
assert_eq!(s.event, Event::Leaf(0));
assert!(!s.is_anonymous());
}
#[test]
fn test_stamp_anonymous() {
let s = Stamp::anonymous();
assert_eq!(s.id, Id::Zero);
assert_eq!(s.event, Event::Leaf(0));
assert!(s.is_anonymous());
}
#[test]
fn test_stamp_new() {
let id = Id::branch(Id::one(), Id::zero());
let event = Event::leaf(3);
let s = Stamp::new(id.clone(), event.clone());
assert_eq!(s.id, id);
assert_eq!(s.event, event);
}
#[test]
fn test_stamp_normalize() {
let id = Id::Branch(Box::new(Id::One), Box::new(Id::One));
let event = Event::Branch(0, Box::new(Event::Leaf(2)), Box::new(Event::Leaf(2)));
let s = Stamp::new(id, event).normalize();
assert_eq!(s.id, Id::One);
assert_eq!(s.event, Event::Leaf(2));
}
#[test]
fn test_stamp_display_seed() {
let s = Stamp::seed();
assert_eq!(format!("{s}"), "(1, 0)");
}
#[test]
fn test_stamp_display_complex() {
let s = Stamp::new(
Id::branch(Id::one(), Id::zero()),
Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2))),
);
assert_eq!(format!("{s}"), "((1, 0), (1, 0, 2))");
}
#[test]
fn test_stamp_equality() {
assert_eq!(Stamp::seed(), Stamp::seed());
assert_eq!(Stamp::anonymous(), Stamp::anonymous());
assert_ne!(Stamp::seed(), Stamp::anonymous());
}
#[test]
fn test_stamp_clone() {
let s = Stamp::new(
Id::branch(Id::one(), Id::branch(Id::zero(), Id::one())),
Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3))),
);
assert_eq!(s, s.clone());
}
#[test]
fn test_id_serde_roundtrip_zero() {
let id = Id::zero();
let json = serde_json::to_string(&id).unwrap();
let deser: Id = serde_json::from_str(&json).unwrap();
assert_eq!(id, deser);
}
#[test]
fn test_id_serde_roundtrip_one() {
let id = Id::one();
let json = serde_json::to_string(&id).unwrap();
let deser: Id = serde_json::from_str(&json).unwrap();
assert_eq!(id, deser);
}
#[test]
fn test_id_serde_roundtrip_branch() {
let id = Id::branch(Id::one(), Id::branch(Id::zero(), Id::one()));
let json = serde_json::to_string(&id).unwrap();
let deser: Id = serde_json::from_str(&json).unwrap();
assert_eq!(id, deser);
}
#[test]
fn test_event_serde_roundtrip_leaf() {
let e = Event::leaf(42);
let json = serde_json::to_string(&e).unwrap();
let deser: Event = serde_json::from_str(&json).unwrap();
assert_eq!(e, deser);
}
#[test]
fn test_event_serde_roundtrip_branch() {
let e = Event::Branch(
3,
Box::new(Event::Leaf(0)),
Box::new(Event::Branch(
1,
Box::new(Event::Leaf(2)),
Box::new(Event::Leaf(0)),
)),
);
let json = serde_json::to_string(&e).unwrap();
let deser: Event = serde_json::from_str(&json).unwrap();
assert_eq!(e, deser);
}
#[test]
fn test_stamp_serde_roundtrip() {
let s = Stamp::new(
Id::branch(Id::one(), Id::branch(Id::zero(), Id::one())),
Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3))),
);
let json = serde_json::to_string(&s).unwrap();
let deser: Stamp = serde_json::from_str(&json).unwrap();
assert_eq!(s, deser);
}
#[test]
fn test_stamp_serde_roundtrip_seed() {
let s = Stamp::seed();
let json = serde_json::to_string(&s).unwrap();
let deser: Stamp = serde_json::from_str(&json).unwrap();
assert_eq!(s, deser);
}
#[test]
fn test_normalization_idempotent_id() {
let id = Id::branch(
Id::branch(Id::one(), Id::zero()),
Id::branch(Id::zero(), Id::one()),
);
let n1 = id.clone().normalize();
let n2 = n1.clone().normalize();
assert_eq!(n1, n2);
}
#[test]
fn test_normalization_idempotent_event() {
let e = Event::Branch(
0,
Box::new(Event::Branch(
1,
Box::new(Event::Leaf(2)),
Box::new(Event::Leaf(3)),
)),
Box::new(Event::Leaf(5)),
);
let n1 = e.clone().normalize();
let n2 = n1.clone().normalize();
assert_eq!(n1, n2);
}
#[test]
fn test_normalization_preserves_semantics() {
let e = Event::Branch(
0,
Box::new(Event::Branch(
0,
Box::new(Event::Leaf(2)),
Box::new(Event::Leaf(2)),
)),
Box::new(Event::Leaf(5)),
);
let min_before = e.min_value();
let max_before = e.max_value();
let normalized = e.normalize();
assert_eq!(normalized.min_value(), min_before);
assert_eq!(normalized.max_value(), max_before);
}
#[test]
fn test_event_branch_with_nested_branches() {
let e = Event::branch(
1,
Event::branch(0, Event::leaf(2), Event::leaf(4)),
Event::leaf(3),
);
assert_eq!(e.min_value(), 3);
assert_eq!(e.max_value(), 5);
}
#[test]
fn test_event_large_values() {
let e = Event::leaf(u32::MAX - 1);
assert_eq!(e.value(), u32::MAX - 1);
assert_eq!(e.min_value(), u32::MAX - 1);
let lifted = e.lift(1);
assert_eq!(lifted.value(), u32::MAX);
}
#[test]
fn test_id_deeply_nested() {
let mut id = Id::one();
for _ in 0..10 {
id = Id::branch(id, Id::zero());
}
assert_eq!(id.depth(), 10);
assert_eq!(id.node_count(), 21);
}
#[test]
fn test_stamp_with_complex_trees() {
let id = Id::branch(Id::branch(Id::one(), Id::zero()), Id::zero());
let event = Event::Branch(
2,
Box::new(Event::Branch(
1,
Box::new(Event::Leaf(0)),
Box::new(Event::Leaf(1)),
)),
Box::new(Event::Leaf(0)),
);
let s = Stamp::new(id, event);
assert!(!s.is_anonymous());
assert_eq!(s.event.min_value(), 2);
assert_eq!(s.event.max_value(), 4);
}
}