pub struct GCounter { /* private fields */ }Expand description
A grow-only counter: one tally per replica, join = pointwise max.
Model: Crdt.GCounter ι = ι → ℕ with the Pi join-semilattice. Applying a
delta is joining it in, so delivery order and redelivery are irrelevant —
SafeMesh.delta_dissemination_sec — and a replica that received bumps B
holds, per coordinate, the max over that coordinate’s bumps —
SafeMesh.deltaGCounter_correct.
Implementations§
Source§impl GCounter
impl GCounter
Sourcepub const MAX_REPLICAS: usize = 4_096
pub const MAX_REPLICAS: usize = 4_096
Maximum constructor domain: 4,096 replicas, matching the default wire version-vector author limit. Storage is at most 32 KiB per G-counter (64 KiB per PN-counter), below the WASM and Python numeric limits.
Sourcepub fn new(n: usize) -> Self
pub fn new(n: usize) -> Self
Fresh counter for n replicas — the lattice bottom ⊥ (all zeros).
§Panics
Panics above Self::MAX_REPLICAS or on allocator refusal. Use
Self::try_new to receive a named error instead.
Sourcepub fn try_new(n: usize) -> Result<Self, CoordinateError>
pub fn try_new(n: usize) -> Result<Self, CoordinateError>
Fresh counter with a domain bounded by Self::MAX_REPLICAS.
The 4,096-replica maximum matches the default wire author limit and
bounds storage to 32 KiB. Larger counts return ReplicaLimitExceeded
before allocation. Admitted counts use the allocator’s zeroed path,
like vec![0; n], without an explicit page-touching initialization loop.
As on main, admitted allocations use vec![0; n]; an out-of-memory
allocator can abort. The cap bounds this request to 32 KiB.
pub fn is_empty(&self) -> bool
Sourcepub fn apply_bump(&mut self, replica: usize, tally: u64)
pub fn apply_bump(&mut self, replica: usize, tally: u64)
Apply the delta SafeMesh.deltaBump replica tally — a single
coordinate on the wire. Joining the delta is max at that coordinate
(Pi.single joined into the state); applying the same bump again is a
no-op (idempotence, SafeMesh.delta_dissemination_sec).
Out-of-range replica is ignored (a malformed delta must not corrupt
state; the Lean model has no such case — Fin n makes it unrepresentable).
Use Self::try_apply_bump to receive an error for an invalid index.
Sourcepub fn try_apply_bump(
&mut self,
replica: usize,
tally: u64,
) -> Result<(), CoordinateError>
pub fn try_apply_bump( &mut self, replica: usize, tally: u64, ) -> Result<(), CoordinateError>
Apply a single-coordinate delta, returning an error for an invalid index.
Checks the coordinate before mutation. On error, the entire counter is
unchanged; on success, behaves exactly like Self::apply_bump, including
accepting an equal or lower tally as a no-op.
Sourcepub fn try_merge(&mut self, other: &GCounter) -> Result<(), MergeError>
pub fn try_merge(&mut self, other: &GCounter) -> Result<(), MergeError>
Checked full-state merge: pointwise max, erroring on a replica-count mismatch instead of silently truncating to the shorter vector (WS1). This is the boundary-safe entry point for state received from an untrusted peer.
Sourcepub fn merge(&mut self, other: &GCounter) -> Result<(), MergeError>
pub fn merge(&mut self, other: &GCounter) -> Result<(), MergeError>
Full-state merge: pointwise max — Crdt.gcounter_merge_apply. A
delta replica and a full-state replica fed the same bumps agree:
SafeMesh.deltaGCounter_matches_full.
Returns MergeError::ReplicaCountMismatch without changing state if
the replica counts differ, just like GCounter::try_merge.
Sourcepub fn value(&self) -> u128
pub fn value(&self) -> u128
The counter’s read: sum of per-replica tallies — Crdt.gcounterValue,
a natural number with no upper bound in the model.
The read is exact for every state this counter can hold: at most
isize::MAX coordinates, each at most u64::MAX, sum to strictly less
than 2^127, so the u128 total never wraps and is never clamped. A
total that no longer fits a narrower integer is still returned whole;
a caller that needs u64 narrows it with u64::try_from and handles
the failure itself.
Trait Implementations§
Source§impl Crdt for GCounter
impl Crdt for GCounter
type Delta = GCounterDelta
Source§fn validate_record(
&self,
id: RecordId,
delta: &Self::Delta,
) -> Result<(), WireError>
fn validate_record( &self, id: RecordId, delta: &Self::Delta, ) -> Result<(), WireError>
Source§fn replica_count(&self) -> Option<usize>
fn replica_count(&self) -> Option<usize>
None for CRDTs without a fixed arity.fn apply_delta(&mut self, delta: Self::Delta)
Source§impl Mergeable for GCounter
impl Mergeable for GCounter
Source§fn merge(&mut self, other: &Self) -> Result<(), MergeError>
fn merge(&mut self, other: &Self) -> Result<(), MergeError>
impl Eq for GCounter
impl StructuralPartialEq for GCounter
Auto Trait Implementations§
impl Freeze for GCounter
impl RefUnwindSafe for GCounter
impl Send for GCounter
impl Sync for GCounter
impl Unpin for GCounter
impl UnsafeUnpin for GCounter
impl UnwindSafe for GCounter
Blanket Implementations§
Source§impl<T> Any for Twhere
T: 'static + ?Sized,
impl<T> Any for Twhere
T: 'static + ?Sized,
Source§fn type_id(&self) -> TypeId
fn type_id(&self) -> TypeId
TypeId of self. Read moreSource§impl<T> Borrow<T> for Twhere
T: ?Sized,
impl<T> Borrow<T> for Twhere
T: ?Sized,
Source§fn borrow(&self) -> &T
fn borrow(&self) -> &T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)self to dest. Read moreSource§impl<T, U> Into<U> for Twhere
U: From<T>,
impl<T, U> Into<U> for Twhere
U: From<T>,
Source§fn into(self) -> U
fn into(self) -> U
Calls U::from(self).
That is, this conversion is whatever the implementation of
From<T> for U chooses to do.