[−][src]Struct cvrdt_exposition::pn_counter::PNCounter
A vectorized counter than can grow or shrink
Panics
Like GCounter
s, any function involving two or more
PNCounter
s (viz. le
and merge
) will panic (via assert_eq!
) if their counts vectors are
not the same length. What's more, since PNCounter
s involve two vectorized counts, any
instantiation (via new
) will also panic if the lengths of the positive and negative count
vectors differ. I'd prefer to check this at compile time (as much as possible) instead, but
- avoiding C++'s template mess is part of what makes Rust great
- Rust doesn't have const generics yet
- this library is meant to be as simple and expository as possible, so I'd like to avoid
fancier things like
generic_array
As mentioned above, operations panic when trying dealing with two or more PNCounter
s of
incompatible sizes:
// this will panic use cvrdt_exposition::{PNCounter, Grow}; let x = PNCounter::new((0, vec![0], vec![0])); let y = PNCounter::new((1, vec![0, 0], vec![0, 0])); x.merge(&y);
We will also get panics if we try to create a new PNCounter
with differing positive
and
negative
lengths:
// this will panic use cvrdt_exposition::{PNCounter, Grow}; let x = PNCounter::new((0, vec![0], vec![0, 0]));
Or if we specify an id
outside the length of the positive
or negative
counts:
// this will panic use cvrdt_exposition::{PNCounter, Grow}; let x = PNCounter::new((17, vec![0], vec![0]));
Difference from references
In the comprehensive study paper and the Wikipedia
article, the vectorized
PNCounter
presumes a local myID()
function that tells our local PNCounter
the index to
update in its counts array. This detail isn't necessary for understanding how their pseudocode
works, but it is required if you're trying to implement a PNCounter
in real code. As such,
we explicitly include the id
as a member of our PNCounter
struct, and make the arbitrary
choice that when merging two PNCounter
s, we take the minimum of their two id
s as the new
one.
Examples
Example usage, including demonstrating some properties:
use cvrdt_exposition::{Grow, PNCounter, Shrink}; let mut x = PNCounter::new((0, vec![0; 2], vec![0; 2])); x.add(()); x.del(()); x.add(()); x.add(()); assert_eq!(x.payload(), (0, vec![3, 0], vec![1, 0])); assert_eq!(x.query(&()), 2); let y = PNCounter::new((1, vec![0, 3], vec![0, 0])); let z = x.merge(&y); assert_eq!(z.payload(), (0, vec![3, 3], vec![1, 0])); assert_eq!(z.payload(), y.merge(&x).payload()); assert_eq!(z.query(&()), 5);
Fields
id: usize
The index for this local PNCounter
where all updates occur
positive: Vec<u64>
The vector of positive counts (additions)
negative: Vec<u64>
The vector of negative counts (deletions)
Trait Implementations
impl Clone for PNCounter
[src]
impl Debug for PNCounter
[src]
impl Grow for PNCounter
[src]
type Payload = (usize, Vec<u64>, Vec<u64>)
The internal state of our CvRDT; sufficient to build a new copy via new
. Required to implement Eq
for testing and verification. Read more
type Update = ()
Message to update our internal state
type Query = ()
Message to query the Value
of our CvRDT
type Value = u64
The response to a Query
fn new(payload: Self::Payload) -> Self
[src]
fn payload(&self) -> Self::Payload
[src]
fn add(&mut self, _update: Self::Update)
[src]
fn le(&self, other: &Self) -> bool
[src]
fn merge(&self, other: &Self) -> Self
[src]
fn query(&self, _query: &Self::Query) -> Self::Value
[src]
impl Shrink for PNCounter
[src]
Auto Trait Implementations
impl RefUnwindSafe for PNCounter
impl Send for PNCounter
impl Sync for PNCounter
impl Unpin for PNCounter
impl UnwindSafe for PNCounter
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
fn to_owned(&self) -> T
[src]
fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,