[][src]Struct cvrdt_exposition::pn_counter::PNCounter

pub struct PNCounter {
    pub id: usize,
    pub positive: Vec<u64>,
    pub negative: Vec<u64>,
}

A vectorized counter than can grow or shrink

Panics

Like GCounters, any function involving two or more PNCounters (viz. le and merge) will panic (via assert_eq!) if their counts vectors are not the same length. What's more, since PNCounters 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 PNCounters of incompatible sizes:

This example panics
// 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 example panics
// 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 example panics
// 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 PNCounters, we take the minimum of their two ids 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

impl Shrink for PNCounter[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.