Skip to main content

bones_core/clock/
itc.rs

1//! Interval Tree Clock (ITC) data structures.
2//!
3//! Implements the ID tree, Event tree, and Stamp types from:
4//! Almeida, Baquero & Fonte (2008) "Interval Tree Clocks".
5//!
6//! - [`Id`] represents a partition of the interval \[0, 1) among agents.
7//! - [`Event`] represents causal history as a binary tree of counters.
8//! - [`Stamp`] combines an ID tree and Event tree into an ITC stamp.
9//!
10//! Trees are automatically normalized to their minimal representation.
11//! Operations (fork, join, event, peek, leq) are in a separate module.
12
13use serde::{Deserialize, Serialize};
14use std::fmt;
15
16// ---------------------------------------------------------------------------
17// ID tree
18// ---------------------------------------------------------------------------
19
20/// An ITC identity tree, partitioning \[0, 1) among participants.
21///
22/// Leaves are either `0` (not owned) or `1` (owned). Interior nodes
23/// split the interval into left and right halves. Normalization collapses
24/// degenerate branches: `Branch(0, 0) → Zero`, `Branch(1, 1) → One`.
25#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
26pub enum Id {
27    /// Leaf 0 — this portion of the interval is not owned.
28    Zero,
29    /// Leaf 1 — this portion of the interval is owned.
30    One,
31    /// Branch splitting the interval into left and right halves.
32    Branch(Box<Self>, Box<Self>),
33}
34
35impl Id {
36    /// Create an anonymous (unowned) identity: leaf 0.
37    #[must_use]
38    pub const fn zero() -> Self {
39        Self::Zero
40    }
41
42    /// Create a seed (fully-owned) identity: leaf 1.
43    #[must_use]
44    pub const fn one() -> Self {
45        Self::One
46    }
47
48    /// Create a branch, automatically normalizing degenerate cases.
49    #[must_use]
50    pub fn branch(left: Self, right: Self) -> Self {
51        match (&left, &right) {
52            (Self::Zero, Self::Zero) => Self::Zero,
53            (Self::One, Self::One) => Self::One,
54            _ => Self::Branch(Box::new(left), Box::new(right)),
55        }
56    }
57
58    /// Returns `true` if this identity owns no interval (is all zeros).
59    #[must_use]
60    pub fn is_zero(&self) -> bool {
61        *self == Self::Zero
62    }
63
64    /// Returns `true` if this identity owns the entire interval (is all ones).
65    #[must_use]
66    pub fn is_one(&self) -> bool {
67        *self == Self::One
68    }
69
70    /// Returns `true` if this is a leaf node (0 or 1).
71    #[must_use]
72    pub const fn is_leaf(&self) -> bool {
73        matches!(self, Self::Zero | Self::One)
74    }
75
76    /// Returns `true` if this is a branch node.
77    #[must_use]
78    pub const fn is_branch(&self) -> bool {
79        matches!(self, Self::Branch(..))
80    }
81
82    /// Depth of the tree (0 for leaves).
83    #[must_use]
84    pub fn depth(&self) -> usize {
85        match self {
86            Self::Zero | Self::One => 0,
87            Self::Branch(l, r) => 1 + l.depth().max(r.depth()),
88        }
89    }
90
91    /// Number of nodes in the tree (leaves + branches).
92    #[must_use]
93    pub fn node_count(&self) -> usize {
94        match self {
95            Self::Zero | Self::One => 1,
96            Self::Branch(l, r) => 1 + l.node_count() + r.node_count(),
97        }
98    }
99
100    /// Normalize the tree to its minimal representation.
101    ///
102    /// This collapses `Branch(0, 0) → 0` and `Branch(1, 1) → 1`
103    /// recursively. Already-normalized trees are returned unchanged.
104    #[must_use]
105    pub fn normalize(self) -> Self {
106        match self {
107            Self::Zero | Self::One => self,
108            Self::Branch(l, r) => {
109                let nl = l.normalize();
110                let nr = r.normalize();
111                Self::branch(nl, nr)
112            }
113        }
114    }
115}
116
117impl fmt::Debug for Id {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        match self {
120            Self::Zero => write!(f, "0"),
121            Self::One => write!(f, "1"),
122            Self::Branch(l, r) => write!(f, "({l:?}, {r:?})"),
123        }
124    }
125}
126
127impl fmt::Display for Id {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        // Display uses the same compact format as Debug
130        fmt::Debug::fmt(self, f)
131    }
132}
133
134// ---------------------------------------------------------------------------
135// Event tree
136// ---------------------------------------------------------------------------
137
138/// An ITC event tree, tracking causal history as a binary tree of counters.
139///
140/// The effective count at any position is the sum of counters along the
141/// root-to-leaf path. Interior nodes carry a base counter that is shared
142/// by both subtrees. Normalization lifts the minimum of two children's
143/// leaf values into the parent and collapses uniform branches.
144#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
145pub enum Event {
146    /// Leaf with a counter value.
147    Leaf(u32),
148    /// Branch with a base counter and left/right subtrees.
149    ///
150    /// The effective value at any leaf in this subtree is `base` plus
151    /// the value accumulated through the child path.
152    Branch(u32, Box<Self>, Box<Self>),
153}
154
155impl Event {
156    /// Create a leaf node with the given counter value.
157    #[must_use]
158    pub const fn leaf(value: u32) -> Self {
159        Self::Leaf(value)
160    }
161
162    /// Create a zero leaf (no events recorded).
163    #[must_use]
164    pub const fn zero() -> Self {
165        Self::Leaf(0)
166    }
167
168    /// Create a branch, automatically normalizing degenerate cases.
169    ///
170    /// Normalization rules:
171    /// - `Branch(n, Leaf(a), Leaf(b))` where `a == b` → `Leaf(n + a)`
172    /// - Otherwise, lifts the minimum of leaf children into the base:
173    ///   `Branch(n, l, r)` → `Branch(n + min, l - min, r - min)`
174    #[must_use]
175    pub fn branch(base: u32, left: Self, right: Self) -> Self {
176        match (&left, &right) {
177            (Self::Leaf(a), Self::Leaf(b)) if a == b => Self::Leaf(base + a),
178            _ => {
179                let min_val = left.min_value().min(right.min_value());
180                if min_val > 0 {
181                    Self::Branch(
182                        base + min_val,
183                        Box::new(left.subtract_base(min_val)),
184                        Box::new(right.subtract_base(min_val)),
185                    )
186                } else {
187                    Self::Branch(base, Box::new(left), Box::new(right))
188                }
189            }
190        }
191    }
192
193    /// Returns `true` if this is a leaf node.
194    #[must_use]
195    pub const fn is_leaf(&self) -> bool {
196        matches!(self, Self::Leaf(_))
197    }
198
199    /// Returns `true` if this is a branch node.
200    #[must_use]
201    pub const fn is_branch(&self) -> bool {
202        matches!(self, Self::Branch(..))
203    }
204
205    /// The base value at this node.
206    ///
207    /// For leaves, this is the counter value. For branches, the base counter.
208    #[must_use]
209    pub const fn value(&self) -> u32 {
210        match self {
211            Self::Leaf(n) | Self::Branch(n, _, _) => *n,
212        }
213    }
214
215    /// The minimum effective value in the entire subtree.
216    ///
217    /// For leaves, this is just the counter. For branches, it is the base
218    /// plus the minimum of the two children's minimums.
219    #[must_use]
220    pub fn min_value(&self) -> u32 {
221        match self {
222            Self::Leaf(n) => *n,
223            Self::Branch(n, l, r) => n + l.min_value().min(r.min_value()),
224        }
225    }
226
227    /// The maximum effective value in the entire subtree.
228    ///
229    /// For leaves, this is just the counter. For branches, it is the base
230    /// plus the maximum of the two children's maximums.
231    #[must_use]
232    pub fn max_value(&self) -> u32 {
233        match self {
234            Self::Leaf(n) => *n,
235            Self::Branch(n, l, r) => n + l.max_value().max(r.max_value()),
236        }
237    }
238
239    /// Depth of the tree (0 for leaves).
240    #[must_use]
241    pub fn depth(&self) -> usize {
242        match self {
243            Self::Leaf(_) => 0,
244            Self::Branch(_, l, r) => 1 + l.depth().max(r.depth()),
245        }
246    }
247
248    /// Number of nodes in the tree (leaves + branches).
249    #[must_use]
250    pub fn node_count(&self) -> usize {
251        match self {
252            Self::Leaf(_) => 1,
253            Self::Branch(_, l, r) => 1 + l.node_count() + r.node_count(),
254        }
255    }
256
257    /// Normalize the tree to its minimal representation.
258    ///
259    /// Recursively normalizes children, then applies:
260    /// - `Branch(n, Leaf(a), Leaf(b))` where `a == b` → `Leaf(n + a)`
261    /// - Lifts the common minimum into the base counter.
262    #[must_use]
263    pub fn normalize(self) -> Self {
264        match self {
265            Self::Leaf(_) => self,
266            Self::Branch(n, l, r) => {
267                let nl = l.normalize();
268                let nr = r.normalize();
269                Self::branch(n, nl, nr)
270            }
271        }
272    }
273
274    /// Lift the tree by adding `delta` to the base/leaf value.
275    #[must_use]
276    pub fn lift(self, delta: u32) -> Self {
277        match self {
278            Self::Leaf(n) => Self::Leaf(n + delta),
279            Self::Branch(n, l, r) => Self::Branch(n + delta, l, r),
280        }
281    }
282
283    /// Subtract `delta` from the base/leaf value.
284    ///
285    /// # Panics
286    ///
287    /// Panics if `delta` exceeds the current base/leaf value. This is
288    /// an internal invariant — callers must ensure `delta <= self.value()`.
289    #[must_use]
290    fn subtract_base(self, delta: u32) -> Self {
291        match self {
292            Self::Leaf(n) => {
293                assert!(delta <= n, "subtract_base: delta {delta} > leaf value {n}");
294                Self::Leaf(n - delta)
295            }
296            Self::Branch(n, l, r) => {
297                assert!(delta <= n, "subtract_base: delta {delta} > branch base {n}");
298                Self::Branch(n - delta, l, r)
299            }
300        }
301    }
302}
303
304impl fmt::Debug for Event {
305    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306        match self {
307            Self::Leaf(n) => write!(f, "{n}"),
308            Self::Branch(n, l, r) => write!(f, "({n}, {l:?}, {r:?})"),
309        }
310    }
311}
312
313impl fmt::Display for Event {
314    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315        fmt::Debug::fmt(self, f)
316    }
317}
318
319// ---------------------------------------------------------------------------
320// Stamp
321// ---------------------------------------------------------------------------
322
323/// An ITC stamp: a pair of (ID tree, Event tree).
324///
325/// The stamp is the fundamental unit of causality tracking in ITC.
326/// Each agent holds a stamp; operations like fork, join, and event
327/// modify the stamp to track causal history.
328#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
329pub struct Stamp {
330    /// The identity partition owned by this stamp.
331    pub id: Id,
332    /// The causal history recorded by this stamp.
333    pub event: Event,
334}
335
336impl Stamp {
337    /// Create a new stamp with the given ID and event trees.
338    #[must_use]
339    pub const fn new(id: Id, event: Event) -> Self {
340        Self { id, event }
341    }
342
343    /// Create the initial seed stamp: owns the full interval with zero events.
344    ///
345    /// This is the starting point for an ITC system. The seed stamp
346    /// owns the entire \[0, 1) interval and has recorded no events.
347    #[must_use]
348    pub const fn seed() -> Self {
349        Self {
350            id: Id::one(),
351            event: Event::zero(),
352        }
353    }
354
355    /// Create an anonymous stamp: owns nothing, zero events.
356    ///
357    /// An anonymous stamp cannot record events but can receive causality
358    /// information through join operations.
359    #[must_use]
360    pub const fn anonymous() -> Self {
361        Self {
362            id: Id::zero(),
363            event: Event::zero(),
364        }
365    }
366
367    /// Returns `true` if this stamp owns no interval.
368    #[must_use]
369    pub fn is_anonymous(&self) -> bool {
370        self.id.is_zero()
371    }
372
373    /// Normalize both the ID and event trees to their minimal representations.
374    #[must_use]
375    pub fn normalize(self) -> Self {
376        Self {
377            id: self.id.normalize(),
378            event: self.event.normalize(),
379        }
380    }
381}
382
383impl fmt::Display for Stamp {
384    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385        write!(f, "({}, {})", self.id, self.event)
386    }
387}
388
389// ---------------------------------------------------------------------------
390// Tests
391// ---------------------------------------------------------------------------
392
393#[cfg(test)]
394mod tests {
395    use super::*;
396
397    // === Id construction ====================================================
398
399    #[test]
400    fn test_id_zero() {
401        let id = Id::zero();
402        assert!(id.is_zero());
403        assert!(!id.is_one());
404        assert!(id.is_leaf());
405        assert!(!id.is_branch());
406        assert_eq!(id.depth(), 0);
407        assert_eq!(id.node_count(), 1);
408    }
409
410    #[test]
411    fn test_id_one() {
412        let id = Id::one();
413        assert!(!id.is_zero());
414        assert!(id.is_one());
415        assert!(id.is_leaf());
416        assert!(!id.is_branch());
417        assert_eq!(id.depth(), 0);
418        assert_eq!(id.node_count(), 1);
419    }
420
421    #[test]
422    fn test_id_branch_distinct_children() {
423        let id = Id::branch(Id::one(), Id::zero());
424        assert!(!id.is_zero());
425        assert!(!id.is_one());
426        assert!(!id.is_leaf());
427        assert!(id.is_branch());
428        assert_eq!(id.depth(), 1);
429        assert_eq!(id.node_count(), 3);
430    }
431
432    // === Id normalization ===================================================
433
434    #[test]
435    fn test_id_branch_both_zero_normalizes() {
436        let id = Id::branch(Id::zero(), Id::zero());
437        assert_eq!(id, Id::Zero);
438        assert!(id.is_zero());
439    }
440
441    #[test]
442    fn test_id_branch_both_one_normalizes() {
443        let id = Id::branch(Id::one(), Id::one());
444        assert_eq!(id, Id::One);
445        assert!(id.is_one());
446    }
447
448    #[test]
449    fn test_id_nested_normalization() {
450        // Branch(Branch(0,0), Branch(1,1)) should normalize to Branch(0, 1)
451        let id = Id::branch(
452            Id::branch(Id::zero(), Id::zero()),
453            Id::branch(Id::one(), Id::one()),
454        );
455        assert_eq!(id, Id::branch(Id::zero(), Id::one()));
456    }
457
458    #[test]
459    fn test_id_deep_normalization() {
460        // (((1,1),(1,1)), ((1,1),(1,1))) → all ones → 1
461        let inner = Id::branch(Id::one(), Id::one()); // → 1
462        let mid = Id::branch(inner.clone(), inner); // → 1
463        let outer = Id::branch(mid.clone(), mid); // → 1
464        assert_eq!(outer, Id::One);
465    }
466
467    #[test]
468    fn test_id_normalize_method() {
469        // Manually construct un-normalized tree
470        let id = Id::Branch(
471            Box::new(Id::Branch(Box::new(Id::Zero), Box::new(Id::Zero))),
472            Box::new(Id::One),
473        );
474        let normalized = id.normalize();
475        assert_eq!(normalized, Id::branch(Id::zero(), Id::one()));
476    }
477
478    #[test]
479    fn test_id_normalize_already_minimal() {
480        let id = Id::branch(Id::one(), Id::zero());
481        let normalized = id.clone().normalize();
482        assert_eq!(id, normalized);
483    }
484
485    // === Id display =========================================================
486
487    #[test]
488    fn test_id_display_zero() {
489        assert_eq!(format!("{}", Id::zero()), "0");
490    }
491
492    #[test]
493    fn test_id_display_one() {
494        assert_eq!(format!("{}", Id::one()), "1");
495    }
496
497    #[test]
498    fn test_id_display_branch() {
499        let id = Id::branch(Id::one(), Id::zero());
500        assert_eq!(format!("{id}"), "(1, 0)");
501    }
502
503    #[test]
504    fn test_id_display_nested() {
505        let id = Id::branch(Id::branch(Id::one(), Id::zero()), Id::zero());
506        assert_eq!(format!("{id}"), "((1, 0), 0)");
507    }
508
509    // === Id equality and clone ==============================================
510
511    #[test]
512    fn test_id_equality() {
513        assert_eq!(Id::zero(), Id::zero());
514        assert_eq!(Id::one(), Id::one());
515        assert_ne!(Id::zero(), Id::one());
516
517        let a = Id::branch(Id::one(), Id::zero());
518        let b = Id::branch(Id::one(), Id::zero());
519        assert_eq!(a, b);
520
521        let c = Id::branch(Id::zero(), Id::one());
522        assert_ne!(a, c);
523    }
524
525    #[test]
526    fn test_id_clone() {
527        let id = Id::branch(Id::one(), Id::branch(Id::zero(), Id::one()));
528        let cloned = id.clone();
529        assert_eq!(id, cloned);
530    }
531
532    // === Id complex structures ==============================================
533
534    #[test]
535    fn test_id_represents_left_half_partition() {
536        // Agent owns left half of [0,1): (1, 0)
537        let id = Id::branch(Id::one(), Id::zero());
538        assert!(!id.is_zero());
539        assert!(!id.is_one());
540        assert_eq!(id.depth(), 1);
541    }
542
543    #[test]
544    fn test_id_represents_quarter_partition() {
545        // Agent owns first quarter: ((1,0), 0)
546        let id = Id::branch(Id::branch(Id::one(), Id::zero()), Id::zero());
547        assert_eq!(id.depth(), 2);
548        assert_eq!(id.node_count(), 5);
549    }
550
551    // === Event construction =================================================
552
553    #[test]
554    fn test_event_zero() {
555        let e = Event::zero();
556        assert!(e.is_leaf());
557        assert!(!e.is_branch());
558        assert_eq!(e.value(), 0);
559        assert_eq!(e.min_value(), 0);
560        assert_eq!(e.max_value(), 0);
561        assert_eq!(e.depth(), 0);
562        assert_eq!(e.node_count(), 1);
563    }
564
565    #[test]
566    fn test_event_leaf() {
567        let e = Event::leaf(5);
568        assert!(e.is_leaf());
569        assert_eq!(e.value(), 5);
570        assert_eq!(e.min_value(), 5);
571        assert_eq!(e.max_value(), 5);
572    }
573
574    #[test]
575    fn test_event_branch_distinct_children() {
576        // Branch(1, Leaf(2), Leaf(3))
577        let e = Event::branch(1, Event::leaf(2), Event::leaf(3));
578        // Since leaf values differ, branch is kept
579        assert!(e.is_branch());
580        assert_eq!(e.value(), 3); // base 1 + lifted min 2
581        assert_eq!(e.min_value(), 3); // 3 + 0 (left after subtraction)
582        assert_eq!(e.max_value(), 4); // 3 + 1 (right after subtraction)
583    }
584
585    // === Event normalization ================================================
586
587    #[test]
588    fn test_event_branch_equal_leaves_normalizes() {
589        // Branch(2, Leaf(3), Leaf(3)) → Leaf(5)
590        let e = Event::branch(2, Event::leaf(3), Event::leaf(3));
591        assert_eq!(e, Event::Leaf(5));
592    }
593
594    #[test]
595    fn test_event_branch_zero_leaves_normalizes() {
596        // Branch(0, Leaf(0), Leaf(0)) → Leaf(0)
597        let e = Event::branch(0, Event::leaf(0), Event::leaf(0));
598        assert_eq!(e, Event::Leaf(0));
599    }
600
601    #[test]
602    fn test_event_branch_lifts_common_minimum() {
603        // Branch(0, Leaf(3), Leaf(5))
604        // min = 3, so becomes Branch(3, Leaf(0), Leaf(2))
605        let e = Event::branch(0, Event::leaf(3), Event::leaf(5));
606        assert_eq!(
607            e,
608            Event::Branch(3, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
609        );
610    }
611
612    #[test]
613    fn test_event_branch_base_plus_lift() {
614        // Branch(2, Leaf(3), Leaf(5))
615        // min of children = 3, so base becomes 2+3=5
616        // Children become Leaf(0), Leaf(2)
617        let e = Event::branch(2, Event::leaf(3), Event::leaf(5));
618        assert_eq!(
619            e,
620            Event::Branch(5, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
621        );
622    }
623
624    #[test]
625    fn test_event_branch_one_child_zero_no_lift() {
626        // Branch(0, Leaf(0), Leaf(3)) — min is 0, no lift needed
627        let e = Event::branch(0, Event::leaf(0), Event::leaf(3));
628        assert_eq!(
629            e,
630            Event::Branch(0, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(3)))
631        );
632    }
633
634    #[test]
635    fn test_event_normalize_method() {
636        // Manually construct un-normalized tree
637        let e = Event::Branch(
638            0,
639            Box::new(Event::Branch(
640                0,
641                Box::new(Event::Leaf(2)),
642                Box::new(Event::Leaf(2)),
643            )),
644            Box::new(Event::Leaf(2)),
645        );
646        let normalized = e.normalize();
647        // Inner branch collapses: Branch(0, Leaf(2), Leaf(2)) → Leaf(2)
648        // Then outer: Branch(0, Leaf(2), Leaf(2)) → Leaf(2)
649        assert_eq!(normalized, Event::Leaf(2));
650    }
651
652    #[test]
653    fn test_event_normalize_partial_collapse() {
654        // Branch(0, Branch(0, Leaf(1), Leaf(1)), Leaf(3))
655        // Inner → Leaf(1)
656        // Outer: Branch(0, Leaf(1), Leaf(3)) → Branch(1, Leaf(0), Leaf(2))
657        let e = Event::Branch(
658            0,
659            Box::new(Event::Branch(
660                0,
661                Box::new(Event::Leaf(1)),
662                Box::new(Event::Leaf(1)),
663            )),
664            Box::new(Event::Leaf(3)),
665        );
666        let normalized = e.normalize();
667        assert_eq!(
668            normalized,
669            Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
670        );
671    }
672
673    // === Event value calculations ===========================================
674
675    #[test]
676    fn test_event_min_value_branch() {
677        // Branch(2, Leaf(1), Leaf(3)) → min = 2 + min(1, 3) = 3
678        let e = Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3)));
679        assert_eq!(e.min_value(), 3);
680    }
681
682    #[test]
683    fn test_event_max_value_branch() {
684        // Branch(2, Leaf(1), Leaf(3)) → max = 2 + max(1, 3) = 5
685        let e = Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3)));
686        assert_eq!(e.max_value(), 5);
687    }
688
689    #[test]
690    fn test_event_min_max_deep() {
691        // Branch(1, Branch(2, Leaf(0), Leaf(3)), Leaf(1))
692        // Left subtree: min=1+2+0=3, max=1+2+3=6
693        // Right subtree: min=max=1+1=2
694        // Overall: min=2, max=6
695        let e = Event::Branch(
696            1,
697            Box::new(Event::Branch(
698                2,
699                Box::new(Event::Leaf(0)),
700                Box::new(Event::Leaf(3)),
701            )),
702            Box::new(Event::Leaf(1)),
703        );
704        assert_eq!(e.min_value(), 2);
705        assert_eq!(e.max_value(), 6);
706    }
707
708    // === Event lift =========================================================
709
710    #[test]
711    fn test_event_lift_leaf() {
712        let e = Event::leaf(3).lift(2);
713        assert_eq!(e, Event::Leaf(5));
714    }
715
716    #[test]
717    fn test_event_lift_branch() {
718        let e = Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)));
719        let lifted = e.lift(3);
720        assert_eq!(
721            lifted,
722            Event::Branch(4, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)))
723        );
724    }
725
726    #[test]
727    fn test_event_lift_zero() {
728        let e = Event::leaf(5);
729        let lifted = e.lift(0);
730        assert_eq!(lifted, Event::Leaf(5));
731    }
732
733    // === Event display ======================================================
734
735    #[test]
736    fn test_event_display_leaf() {
737        assert_eq!(format!("{}", Event::leaf(7)), "7");
738    }
739
740    #[test]
741    fn test_event_display_branch() {
742        let e = Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2)));
743        assert_eq!(format!("{e}"), "(1, 0, 2)");
744    }
745
746    // === Event equality and clone ===========================================
747
748    #[test]
749    fn test_event_equality() {
750        assert_eq!(Event::zero(), Event::zero());
751        assert_eq!(Event::leaf(3), Event::leaf(3));
752        assert_ne!(Event::leaf(3), Event::leaf(4));
753    }
754
755    #[test]
756    fn test_event_clone() {
757        let e = Event::Branch(
758            1,
759            Box::new(Event::Branch(
760                0,
761                Box::new(Event::Leaf(1)),
762                Box::new(Event::Leaf(2)),
763            )),
764            Box::new(Event::Leaf(3)),
765        );
766        let cloned = e.clone();
767        assert_eq!(e, cloned);
768    }
769
770    // === Event depth and node count =========================================
771
772    #[test]
773    fn test_event_depth_nested() {
774        let e = Event::Branch(
775            0,
776            Box::new(Event::Branch(
777                0,
778                Box::new(Event::Leaf(0)),
779                Box::new(Event::Leaf(1)),
780            )),
781            Box::new(Event::Leaf(0)),
782        );
783        assert_eq!(e.depth(), 2);
784    }
785
786    #[test]
787    fn test_event_node_count_nested() {
788        // Branch(0, Branch(0, Leaf(0), Leaf(1)), Leaf(0))
789        // = 1 + (1 + 1 + 1) + 1 = 5
790        let e = Event::Branch(
791            0,
792            Box::new(Event::Branch(
793                0,
794                Box::new(Event::Leaf(0)),
795                Box::new(Event::Leaf(1)),
796            )),
797            Box::new(Event::Leaf(0)),
798        );
799        assert_eq!(e.node_count(), 5);
800    }
801
802    // === Stamp construction =================================================
803
804    #[test]
805    fn test_stamp_seed() {
806        let s = Stamp::seed();
807        assert_eq!(s.id, Id::One);
808        assert_eq!(s.event, Event::Leaf(0));
809        assert!(!s.is_anonymous());
810    }
811
812    #[test]
813    fn test_stamp_anonymous() {
814        let s = Stamp::anonymous();
815        assert_eq!(s.id, Id::Zero);
816        assert_eq!(s.event, Event::Leaf(0));
817        assert!(s.is_anonymous());
818    }
819
820    #[test]
821    fn test_stamp_new() {
822        let id = Id::branch(Id::one(), Id::zero());
823        let event = Event::leaf(3);
824        let s = Stamp::new(id.clone(), event.clone());
825        assert_eq!(s.id, id);
826        assert_eq!(s.event, event);
827    }
828
829    #[test]
830    fn test_stamp_normalize() {
831        let id = Id::Branch(Box::new(Id::One), Box::new(Id::One));
832        let event = Event::Branch(0, Box::new(Event::Leaf(2)), Box::new(Event::Leaf(2)));
833        let s = Stamp::new(id, event).normalize();
834        assert_eq!(s.id, Id::One);
835        assert_eq!(s.event, Event::Leaf(2));
836    }
837
838    // === Stamp display ======================================================
839
840    #[test]
841    fn test_stamp_display_seed() {
842        let s = Stamp::seed();
843        assert_eq!(format!("{s}"), "(1, 0)");
844    }
845
846    #[test]
847    fn test_stamp_display_complex() {
848        let s = Stamp::new(
849            Id::branch(Id::one(), Id::zero()),
850            Event::Branch(1, Box::new(Event::Leaf(0)), Box::new(Event::Leaf(2))),
851        );
852        assert_eq!(format!("{s}"), "((1, 0), (1, 0, 2))");
853    }
854
855    // === Stamp equality and clone ===========================================
856
857    #[test]
858    fn test_stamp_equality() {
859        assert_eq!(Stamp::seed(), Stamp::seed());
860        assert_eq!(Stamp::anonymous(), Stamp::anonymous());
861        assert_ne!(Stamp::seed(), Stamp::anonymous());
862    }
863
864    #[test]
865    fn test_stamp_clone() {
866        let s = Stamp::new(
867            Id::branch(Id::one(), Id::branch(Id::zero(), Id::one())),
868            Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3))),
869        );
870        assert_eq!(s, s.clone());
871    }
872
873    // === Serde roundtrip ====================================================
874
875    #[test]
876    fn test_id_serde_roundtrip_zero() {
877        let id = Id::zero();
878        let json = serde_json::to_string(&id).unwrap();
879        let deser: Id = serde_json::from_str(&json).unwrap();
880        assert_eq!(id, deser);
881    }
882
883    #[test]
884    fn test_id_serde_roundtrip_one() {
885        let id = Id::one();
886        let json = serde_json::to_string(&id).unwrap();
887        let deser: Id = serde_json::from_str(&json).unwrap();
888        assert_eq!(id, deser);
889    }
890
891    #[test]
892    fn test_id_serde_roundtrip_branch() {
893        let id = Id::branch(Id::one(), Id::branch(Id::zero(), Id::one()));
894        let json = serde_json::to_string(&id).unwrap();
895        let deser: Id = serde_json::from_str(&json).unwrap();
896        assert_eq!(id, deser);
897    }
898
899    #[test]
900    fn test_event_serde_roundtrip_leaf() {
901        let e = Event::leaf(42);
902        let json = serde_json::to_string(&e).unwrap();
903        let deser: Event = serde_json::from_str(&json).unwrap();
904        assert_eq!(e, deser);
905    }
906
907    #[test]
908    fn test_event_serde_roundtrip_branch() {
909        let e = Event::Branch(
910            3,
911            Box::new(Event::Leaf(0)),
912            Box::new(Event::Branch(
913                1,
914                Box::new(Event::Leaf(2)),
915                Box::new(Event::Leaf(0)),
916            )),
917        );
918        let json = serde_json::to_string(&e).unwrap();
919        let deser: Event = serde_json::from_str(&json).unwrap();
920        assert_eq!(e, deser);
921    }
922
923    #[test]
924    fn test_stamp_serde_roundtrip() {
925        let s = Stamp::new(
926            Id::branch(Id::one(), Id::branch(Id::zero(), Id::one())),
927            Event::Branch(2, Box::new(Event::Leaf(1)), Box::new(Event::Leaf(3))),
928        );
929        let json = serde_json::to_string(&s).unwrap();
930        let deser: Stamp = serde_json::from_str(&json).unwrap();
931        assert_eq!(s, deser);
932    }
933
934    #[test]
935    fn test_stamp_serde_roundtrip_seed() {
936        let s = Stamp::seed();
937        let json = serde_json::to_string(&s).unwrap();
938        let deser: Stamp = serde_json::from_str(&json).unwrap();
939        assert_eq!(s, deser);
940    }
941
942    // === Normalization invariants ===========================================
943
944    #[test]
945    fn test_normalization_idempotent_id() {
946        let id = Id::branch(
947            Id::branch(Id::one(), Id::zero()),
948            Id::branch(Id::zero(), Id::one()),
949        );
950        let n1 = id.clone().normalize();
951        let n2 = n1.clone().normalize();
952        assert_eq!(n1, n2);
953    }
954
955    #[test]
956    fn test_normalization_idempotent_event() {
957        let e = Event::Branch(
958            0,
959            Box::new(Event::Branch(
960                1,
961                Box::new(Event::Leaf(2)),
962                Box::new(Event::Leaf(3)),
963            )),
964            Box::new(Event::Leaf(5)),
965        );
966        let n1 = e.clone().normalize();
967        let n2 = n1.clone().normalize();
968        assert_eq!(n1, n2);
969    }
970
971    #[test]
972    fn test_normalization_preserves_semantics() {
973        // Normalizing should not change min/max values
974        let e = Event::Branch(
975            0,
976            Box::new(Event::Branch(
977                0,
978                Box::new(Event::Leaf(2)),
979                Box::new(Event::Leaf(2)),
980            )),
981            Box::new(Event::Leaf(5)),
982        );
983        let min_before = e.min_value();
984        let max_before = e.max_value();
985        let normalized = e.normalize();
986        assert_eq!(normalized.min_value(), min_before);
987        assert_eq!(normalized.max_value(), max_before);
988    }
989
990    // === Edge cases =========================================================
991
992    #[test]
993    fn test_event_branch_with_nested_branches() {
994        // Complex nested structure that partially normalizes
995        let e = Event::branch(
996            1,
997            Event::branch(0, Event::leaf(2), Event::leaf(4)),
998            Event::leaf(3),
999        );
1000        // Inner: branch(0, leaf(2), leaf(4)) → Branch(2, Leaf(0), Leaf(2))
1001        // Outer: branch(1, Branch(2, Leaf(0), Leaf(2)), Leaf(3))
1002        //   min of children: min(Branch(2, L0, L2).min_value(), 3) = min(2, 3) = 2
1003        //   base: 1 + 2 = 3
1004        //   left: Branch(2-2=0, L0, L2) = Branch(0, L0, L2)
1005        //   right: Leaf(3-2=1)
1006        assert_eq!(e.min_value(), 3);
1007        assert_eq!(e.max_value(), 5);
1008    }
1009
1010    #[test]
1011    fn test_event_large_values() {
1012        let e = Event::leaf(u32::MAX - 1);
1013        assert_eq!(e.value(), u32::MAX - 1);
1014        assert_eq!(e.min_value(), u32::MAX - 1);
1015        let lifted = e.lift(1);
1016        assert_eq!(lifted.value(), u32::MAX);
1017    }
1018
1019    #[test]
1020    fn test_id_deeply_nested() {
1021        // Build a 10-level deep ID tree
1022        let mut id = Id::one();
1023        for _ in 0..10 {
1024            id = Id::branch(id, Id::zero());
1025        }
1026        assert_eq!(id.depth(), 10);
1027        // node_count: 10 branches + 10 zero leaves + 1 one leaf = 21
1028        assert_eq!(id.node_count(), 21);
1029    }
1030
1031    #[test]
1032    fn test_stamp_with_complex_trees() {
1033        // Realistic stamp after several fork operations
1034        let id = Id::branch(Id::branch(Id::one(), Id::zero()), Id::zero());
1035        let event = Event::Branch(
1036            2,
1037            Box::new(Event::Branch(
1038                1,
1039                Box::new(Event::Leaf(0)),
1040                Box::new(Event::Leaf(1)),
1041            )),
1042            Box::new(Event::Leaf(0)),
1043        );
1044        let s = Stamp::new(id, event);
1045        assert!(!s.is_anonymous());
1046        assert_eq!(s.event.min_value(), 2);
1047        assert_eq!(s.event.max_value(), 4);
1048    }
1049}