use minisketch_rs::Minisketch;
fn sub_sketches(s1: &[u8], s2: &[u8], d: usize, seed: Option<u64>) -> Vec<u8> {
let mut a = create_minisketch(d, seed);
if let Some(seed) = seed {
a.set_seed(seed);
}
a.deserialize(s1);
let mut b = create_minisketch(d, seed);
if let Some(seed) = seed {
b.set_seed(seed);
}
b.deserialize(s2);
a.merge(&b).expect("Sketch sub merge");
let mut sketch = vec![0u8; a.serialized_size()];
a.serialize(&mut sketch).expect("Serialize sketch sub");
sketch
}
fn sketch_from_range(
range: impl IntoIterator<Item = u64>,
capacity: usize,
seed: Option<u64>,
) -> Minisketch {
let mut sketch = create_minisketch(capacity, seed);
for i in range {
sketch.add(i);
}
sketch
}
fn create_minisketch(capacity: usize, seed: Option<u64>) -> Minisketch {
let mut minisketch = Minisketch::try_new(64, 0, capacity).unwrap();
if let Some(seed) = seed {
minisketch.set_seed(seed);
}
minisketch
}
fn serialize_sketch(sketch: Minisketch) -> Vec<u8> {
let mut buf = vec![0u8; sketch.serialized_size()];
sketch.serialize(&mut buf).expect("Minisketch serialize");
buf
}
fn reconcile(
sketch_a: &[u8],
sketch_b: &[u8],
capacity: usize,
seed: Option<u64>,
) -> Result<Vec<u64>, ()> {
let mut a = create_minisketch(capacity, seed);
a.deserialize(sketch_a);
let mut b = create_minisketch(capacity, seed);
b.deserialize(sketch_b);
a.merge(&b).expect("Minisketch merge");
let mut diffs = vec![0u64; capacity];
let num_diffs = a.decode(&mut diffs).map_err(|_| ())?;
Ok(diffs.into_iter().take(num_diffs).collect())
}
fn example(capacity: usize) -> Result<Vec<u64>, ()> {
let seed = None;
let a = 0..32;
let b = 0..8;
let set_diff = a.clone().into_iter().filter(|e| !b.contains(e)).count();
println!(
"Alice's set: {:?}",
a.clone().into_iter().collect::<Vec<_>>()
);
println!("Bob's set: {:?}", b.clone().into_iter().collect::<Vec<_>>());
let b_half = b
.clone()
.into_iter()
.enumerate()
.filter(|(i, _)| *i % 2 == 0)
.map(|(_, n)| n)
.collect::<Vec<_>>();
let a_half = a
.clone()
.into_iter()
.enumerate()
.filter(|(i, _)| *i % 2 == 0)
.map(|(_, n)| n)
.collect::<Vec<_>>();
let alice_set_full = sketch_from_range(a, capacity, seed);
let a_whole = serialize_sketch(alice_set_full);
let a_half = serialize_sketch(sketch_from_range(a_half, capacity, seed));
let bob_set_full = sketch_from_range(b, capacity, seed);
let b_whole = serialize_sketch(bob_set_full);
let b_half = serialize_sketch(sketch_from_range(b_half, capacity, seed));
println!("Trying simple reconciliation");
let simple = reconcile(&a_whole, &b_whole, capacity, seed);
if let Err(()) = simple {
println!(
"Error. Difference exceeds sketch capacity: {} > {}",
set_diff, capacity
);
println!("Trying bisection");
let a_minus_a_2 = sub_sketches(&a_whole, &a_half, capacity, seed);
let b_minus_b_2 = sub_sketches(&b_whole, &b_half, capacity, seed);
let res_1 = reconcile(&a_half, &b_half, capacity, seed);
let res_2 = reconcile(&a_minus_a_2, &b_minus_b_2, capacity, seed);
let res = res_1.and_then(|diffs1| {
res_2.and_then(|diffs2| {
Ok(diffs1
.into_iter()
.chain(diffs2.into_iter())
.collect::<Vec<_>>())
})
});
res
} else {
Ok(simple.unwrap())
}
}
pub fn main() {
let capacity = 16;
match example(capacity) {
Ok(mut diffs) => {
diffs.sort();
println!("Success!");
println!("Differences: {:?}", diffs);
}
Err(()) => println!("Example failed"),
}
}