Skip to main content

commonware_utils/bitmap/historical/
mod.rs

1//! A historical wrapper around [crate::bitmap::Prunable] that maintains snapshots via diffs.
2//!
3//! The Historical bitmap maintains one full [crate::bitmap::Prunable] bitmap (the current/head state).
4//! All historical states are represented as diffs, not full bitmap clones.
5//!
6//! Uses a type-state pattern to track whether the bitmap is clean (no pending mutations) or
7//! dirty (has pending mutations). This provides compile-time guarantees about when mutations
8//! are allowed.
9//!
10//! # Examples
11//!
12//! ## Usage
13//!
14//! ```
15//! # use commonware_utils::bitmap::historical::BitMap;
16//! let bitmap: BitMap<4> = BitMap::new();
17//!
18//! // Transition to dirty state to make mutations
19//! let mut dirty = bitmap.into_dirty();
20//! dirty.push(true);
21//! dirty.push(false);
22//!
23//! // Commit changes and return to clean state
24//! let bitmap = dirty.commit(1).unwrap();
25//!
26//! assert_eq!(bitmap.len(), 2);
27//! assert!(bitmap.get_bit(0));
28//! assert!(!bitmap.get_bit(1));
29//! ```
30//!
31//! ## Usage with closure
32//!
33//! ```
34//! # use commonware_utils::bitmap::historical::BitMap;
35//! let mut bitmap: BitMap<4> = BitMap::new();
36//!
37//! bitmap = bitmap.apply_batch(1, |dirty| {
38//!     dirty.push(true);
39//!     dirty.push(false);
40//! }).unwrap();
41//!
42//! assert_eq!(bitmap.len(), 2);
43//! assert!(bitmap.get_bit(0));
44//! assert!(!bitmap.get_bit(1));
45//! ```
46//!
47//! ## Read-Through Semantics
48//!
49//! ```
50//! # use commonware_utils::bitmap::historical::BitMap;
51//! let mut bitmap: BitMap<4> = BitMap::new();
52//! bitmap = bitmap.apply_batch(1, |dirty| { dirty.push(false); }).unwrap();
53//!
54//! // Before modification
55//! assert!(!bitmap.get_bit(0));
56//!
57//! let mut dirty = bitmap.into_dirty();
58//! dirty.set_bit(0, true);
59//!
60//! // Read through dirty state sees the modification
61//! assert!(dirty.get_bit(0));
62//!
63//! let bitmap = dirty.commit(2).unwrap();
64//!
65//! // After commit, modification is in current
66//! assert!(bitmap.get_bit(0));
67//! ```
68//!
69//! ## Abort Mutations
70//!
71//! ```
72//! # use commonware_utils::bitmap::historical::BitMap;
73//! let mut bitmap: BitMap<4> = BitMap::new();
74//! bitmap = bitmap.apply_batch(1, |dirty| { dirty.push(true); }).unwrap();
75//! let len_before = bitmap.len();
76//!
77//! // Make changes in dirty state
78//! let mut dirty = bitmap.into_dirty();
79//! dirty.push(true);
80//! dirty.push(false);
81//!
82//! // Abort to discard changes and return to clean state
83//! let bitmap = dirty.abort();
84//!
85//! assert_eq!(bitmap.len(), len_before); // Unchanged
86//! ```
87//!
88//! ## Commit History Management
89//!
90//! ```
91//! # use commonware_utils::bitmap::historical::BitMap;
92//! let mut bitmap: BitMap<4> = BitMap::new();
93//! for i in 1..=5 {
94//!     bitmap = bitmap.apply_batch(i, |dirty| {
95//!         dirty.push(true);
96//!     }).unwrap();
97//! }
98//!
99//! assert_eq!(bitmap.commits().count(), 5);
100//!
101//! // Prune old commits
102//! bitmap.prune_commits_before(3);
103//! assert_eq!(bitmap.commits().count(), 3);
104//! ```
105
106mod bitmap;
107pub use bitmap::{BitMap, Clean, CleanBitMap, Dirty, DirtyBitMap, State};
108mod error;
109pub use error::Error;
110
111#[cfg(test)]
112mod tests;