Skip to main content

VersionVector

Struct VersionVector 

Source
pub struct VersionVector { /* private fields */ }
Expand description

Per-replica contiguous prefixes for anti-entropy pulls.

get(replica) == n means every sequence 1..=n for that replica is known. Later records that arrive before earlier records must not advance this prefix, otherwise since could hide gaps. Sequence zero is acknowledged independently by zero_replicas; it is not implied by a positive prefix. The built-in wire codec carries both Self::entries and Self::zero_replicas. Custom version exchanges must carry both too. A receiver can rebuild the vector with Self::from_peer_prefixes after checking application-owned author and zero-acknowledgement budgets, as below; record payloads are not required. Legacy prefix-only exchanges cannot acknowledge zeros and will keep receiving them until upgraded.

These are claims about the sending peer’s log. The caller is responsible for their truth: neither observe nor since checks possession of record payloads. Fabricated IDs can acknowledge missing records and cause since to omit them. Use crate::EventLog::version to derive claims from records actually admitted.

Checked reconstruction validates each positive prefix, then clones both collections: for r authors and z zero acknowledgements it takes O(r + z) time and O(r + z) additional space, independently of the claimed sequences. Bound both collection sizes before reconstruction and enforce transport byte limits before decoding to bound the input allocation itself. Zero-valued prefix entries are noncanonical and are rejected by the checked constructor; only zero_replicas() acknowledges sequence zero.

use safemesh_crdt::{EventLog, VersionVector};
use std::collections::{BTreeMap, BTreeSet};

fn receive(
    prefixes: &BTreeMap<u64, u64>, zeros: &BTreeSet<u64>,
    author_budget: usize, zero_budget: usize,
) -> Result<VersionVector, &'static str> {
    if prefixes.len() > author_budget || zeros.len() > zero_budget {
        return Err("peer version exceeds application budget");
    }
    VersionVector::from_peer_prefixes(prefixes, zeros).map_err(|_| "invalid prefix")
}

let mut peer = EventLog::new();
peer.append(&mut safemesh_crdt::GSet::new(), 7, 42u64).unwrap();
// Carry both collections over the application's transport.
let prefixes = peer.version().entries().clone();
let zeros = peer.version().zero_replicas().clone();
// This example has one publisher and allocates no sequence-zero records.
let received = receive(&prefixes, &zeros, 1, 0).unwrap();
assert_eq!(&received, peer.version());
assert_eq!(peer.since(&received), peer.since(peer.version()));

Implementations§

Source§

impl VersionVector

Source

pub fn from_wire_bytes_with_limits( bytes: &[u8], limits: VersionVectorLimits, ) -> Result<Self, WireError>

Decode with explicit author and sequence-zero acknowledgement budgets. Claimed entry counts are checked before reading or allocating entries.

Source§

impl VersionVector

Source

pub fn new() -> Self

Source

pub fn from_peer_prefixes( entries: &BTreeMap<u64, u64>, zero_replicas: &BTreeSet<u64>, ) -> Result<Self, VersionVectorError>

Reconstruct a vector from a peer’s canonical positive prefixes and independent sequence-zero acknowledgements.

Accepts every positive u64 prefix, including u64::MAX, without iterating over sequences. Zero remains noncanonical: use zero_replicas. This method imposes no collection budget. Use Self::from_peer_prefixes_with_limits to enforce author and zero-acknowledgement budgets before validation or cloning. Callers must retain three application-owned input limits:

  • author count bounds prefix validation and map cloning;
  • zero-acknowledgement count bounds set cloning;
  • encoded byte size, enforced before decoding, bounds input allocation and parsing (including duplicate entries before collection deduplication).

The built-in wire decoder has default entry ceilings; callers can choose their own limits. This constructor imposes no universal application budget. Reconstruction takes O(entries.len() + zero_replicas.len()) time and space.

Source

pub fn from_peer_prefixes_with_limits( entries: &BTreeMap<u64, u64>, zero_replicas: &BTreeSet<u64>, limits: VersionVectorLimits, ) -> Result<Self, VersionVectorLimitError>

Reconstruct a peer version with caller-supplied collection budgets.

Checks author count first, then zero-acknowledgement count, before validating prefixes or cloning either collection. If both budgets are exceeded, returns VersionVectorLimitError::AuthorLimitExceeded. No partial vector is returned. Exact limits are accepted. VersionVectorLimits::default preserves the unbounded constructor’s values and wraps its errors in VersionVectorLimitError::Prefix. These checks do not bound decoding or input allocation: callers must enforce encoded-byte and entry budgets at their decoding boundary too.

Source

pub fn get(&self, replica: u64) -> u64

Source

pub fn observe(&mut self, id: RecordId)

Advance this prefix only when id is the next contiguous sequence. A missing sequence keeps later records outside the prefix until it arrives.

Use EventLog to ingest out-of-order records; the log remembers gaps and advances this vector once the prefix is complete.

Source

pub fn includes(&self, id: RecordId) -> bool

Return true for an acknowledged zero or a sequence in the writer’s contiguous prefix.

Source

pub fn entries(&self) -> &BTreeMap<u64, u64>

Positive contiguous prefixes only; does not describe zero possession.

Source

pub fn zero_replicas(&self) -> &BTreeSet<u64>

Authors whose sequence-zero record has been observed.

Trait Implementations§

Source§

impl Clone for VersionVector

Source§

fn clone(&self) -> VersionVector

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for VersionVector

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for VersionVector

Source§

fn default() -> VersionVector

Returns the “default value” for a type. Read more
Source§

impl PartialEq for VersionVector

Source§

fn eq(&self, other: &VersionVector) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl WireDecode for VersionVector

Source§

fn decode_wire(cursor: &mut WireCursor<'_>) -> Result<Self, WireError>

Source§

fn decode_wire_with_collection_limits( cursor: &mut WireCursor<'_>, _limits: CollectionLimits, ) -> Result<Self, WireError>

Decode a nested payload with a collection budget. Other payload types retain their ordinary decoder unless they implement this method.
Source§

fn decode_wire_with_limits( cursor: &mut WireCursor<'_>, collections: CollectionLimits, _max_records: Option<usize>, ) -> Result<Self, WireError>

Decode a payload nested in an EventLog with its record budget.
Source§

fn from_wire_bytes_with_collection_limits( bytes: &[u8], limits: CollectionLimits, ) -> Result<Self, WireError>

Decode a complete wire value with an explicit collection ceiling.
Source§

fn from_wire_bytes(bytes: &[u8]) -> Result<Self, WireError>

Source§

impl WireEncode for VersionVector

Source§

fn encode_wire(&self, out: &mut Vec<u8>) -> Result<(), WireError>

Source§

fn to_wire_bytes(&self) -> Result<Vec<u8>, WireError>

Source§

impl WireSchema for VersionVector

Source§

const REQUIRES_ARITY: bool = false

Source§

fn wire_schema() -> Cow<'static, [u8]>

Borrow fixed identities; return owned bytes for composed schemas.
Source§

impl Eq for VersionVector

Source§

impl StructuralPartialEq for VersionVector

Auto Trait Implementations§

§

impl Freeze for VersionVector

§

impl RefUnwindSafe for VersionVector

§

impl Send for VersionVector

§

impl Sync for VersionVector

§

impl Unpin for VersionVector

§

impl UnsafeUnpin for VersionVector

§

impl UnwindSafe for VersionVector

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.