use std::marker::PhantomData;
use crate::AsView;
use crate::{node::child_bit as node_child_bit, prefix::mask_from_prefix_len, Prefix};
use super::iter::ViewIter;
use super::TrieView;
#[derive(Clone)]
pub struct DifferenceView<'a, L, R> {
left: L,
right: Option<R>,
_phantom: PhantomData<&'a ()>,
}
impl<'a, L, R> DifferenceView<'a, L, R>
where
L: TrieView<'a>,
R: TrieView<'a, P = L::P>,
{
pub(crate) fn new(left: L, right: R) -> Self {
let right = align_right(&left, right);
Self {
left,
right,
_phantom: PhantomData,
}
}
}
fn align_right<'a, L, R>(left: &L, right: R) -> Option<R>
where
L: TrieView<'a>,
R: TrieView<'a, P = L::P>,
{
let min_prefix_len = left.prefix_len().min(right.prefix_len());
let mask = mask_from_prefix_len(min_prefix_len as u8);
if left.key() & mask != right.key() & mask {
return None; }
match right.depth().cmp(&left.depth()) {
std::cmp::Ordering::Less => {
right.navigate_to(left.key(), left.prefix_len())
}
std::cmp::Ordering::Equal => {
Some(right)
}
std::cmp::Ordering::Greater => {
Some(right)
}
}
}
impl<'a, L, R> TrieView<'a> for DifferenceView<'a, L, R>
where
L: TrieView<'a>,
R: TrieView<'a, P = L::P>,
{
type P = L::P;
type T = L::T;
#[inline]
fn depth(&self) -> u32 {
self.left.depth()
}
#[inline]
fn key(&self) -> <L::P as Prefix>::R {
self.left.key()
}
#[inline]
fn prefix_len(&self) -> u32 {
self.left.prefix_len()
}
#[inline]
fn data_bitmap(&self) -> u32 {
match &self.right {
None => self.left.data_bitmap(),
Some(r) => {
if r.depth() == self.left.depth() {
self.left.data_bitmap() & !r.data_bitmap()
} else {
self.left.data_bitmap()
}
}
}
}
#[inline]
fn child_bitmap(&self) -> u32 {
self.left.child_bitmap()
}
#[inline]
unsafe fn get_data(&mut self, data_bit: u32) -> L::T {
self.left.get_data(data_bit)
}
unsafe fn get_child(&mut self, child_bit: u32) -> Self {
let l_child = self.left.get_child(child_bit);
let r_child = match &mut self.right {
None => None,
Some(r) => {
if r.depth() == self.left.depth() {
if (r.child_bitmap() >> child_bit) & 1 == 1 {
Some(r.get_child(child_bit))
} else {
None }
} else {
let toward_r = node_child_bit(self.left.depth(), r.key());
if child_bit == toward_r {
Some(self.right.take().unwrap())
} else {
None
}
}
}
};
DifferenceView {
left: l_child,
right: r_child,
_phantom: PhantomData,
}
}
unsafe fn reposition(&mut self, key: <L::P as Prefix>::R, prefix_len: u32) {
self.left.reposition(key, prefix_len);
}
}
impl<'a, L, R> IntoIterator for DifferenceView<'a, L, R>
where
L: TrieView<'a>,
R: TrieView<'a, P = L::P>,
{
type Item = (L::P, L::T);
type IntoIter = ViewIter<'a, DifferenceView<'a, L, R>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, L, R> AsView<'a> for DifferenceView<'a, L, R>
where
L: TrieView<'a>,
R: TrieView<'a, P = L::P>,
{
type P = L::P;
type View = Self;
fn view(self) -> Self {
self
}
}
#[cfg(test)]
mod tests {
use crate::{
Prefix,
{
trieview::{AsView, TrieView},
PrefixMap,
},
};
type P = (u32, u8);
fn p(repr: u32, len: u8) -> P {
P::from_repr_len(repr, len)
}
fn map_from(entries: &[(u32, u8, i32)]) -> PrefixMap<P, i32> {
let mut m = PrefixMap::new();
for &(repr, len, val) in entries {
m.insert(p(repr, len), val);
}
m
}
fn collect_diff<'a>(iter: impl Iterator<Item = (P, &'a i32)>) -> Vec<(P, i32)> {
iter.map(|(p, v)| (p, *v)).collect()
}
#[test]
fn diff_basic() {
let a = map_from(&[
(0x0a000000, 8, 1),
(0x0a010000, 16, 2),
(0x0a020000, 16, 3),
(0x0b000000, 8, 4),
]);
let b = map_from(&[
(0x0a000000, 8, 10), (0x0a020000, 16, 30), (0x0c000000, 8, 99), ]);
let got = collect_diff(a.view().difference(b.view()).into_iter());
assert_eq!(
got,
vec![
(p(0x0a010000, 16), 2), (p(0x0b000000, 8), 4), ]
);
}
#[test]
fn diff_no_overlap() {
let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
let b = map_from(&[(0x0b000000, 8, 10), (0x0c000000, 8, 20)]);
let got = collect_diff(a.view().difference(b.view()).into_iter());
assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a010000, 16), 2),]);
}
#[test]
fn diff_b_superset() {
let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
let b = map_from(&[
(0x0a000000, 8, 10),
(0x0a010000, 16, 20),
(0x0b000000, 8, 99),
]);
let got = collect_diff(a.view().difference(b.view()).into_iter());
assert!(got.is_empty());
}
#[test]
fn diff_b_empty() {
let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
let b: PrefixMap<P, i32> = PrefixMap::new();
let got = collect_diff(a.view().difference(b.view()).into_iter());
assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a010000, 16), 2),]);
}
#[test]
fn diff_a_empty() {
let a: PrefixMap<P, i32> = PrefixMap::new();
let b = map_from(&[(0x0a000000, 8, 10)]);
assert!(a.view().difference(b.view()).into_iter().next().is_none());
}
#[test]
fn diff_large_same_depth() {
let a = map_from(&[
(0x01000000, 8, 1),
(0x0a000000, 8, 10),
(0x0a010000, 16, 11),
(0x0a010100, 24, 12),
(0x0a020000, 16, 13),
(0x0b000000, 8, 20),
(0x0b010000, 16, 21),
(0x64000000, 8, 100),
(0xc0a80000, 16, 200),
]);
let b = map_from(&[
(0x0a000000, 8, 99), (0x0a010100, 24, 99), (0x0b000000, 8, 99), (0x64000000, 8, 99), (0xc0a80100, 24, 99), ]);
let got = collect_diff(a.view().difference(b.view()).into_iter());
assert_eq!(
got,
vec![
(p(0x01000000, 8), 1), (p(0x0a010000, 16), 11), (p(0x0a020000, 16), 13), (p(0x0b010000, 16), 21), (p(0xc0a80000, 16), 200), ]
);
}
#[test]
fn diff_find_then_iter() {
let a = map_from(&[
(0x0a000000, 8, 1),
(0x0a010000, 16, 2),
(0x0a010100, 24, 3),
(0x0b000000, 8, 4),
]);
let b = map_from(&[
(0x0a000000, 8, 10),
(0x0a010000, 16, 20), ]);
let got = collect_diff(
a.view()
.difference(b.view())
.find(&p(0x0a010000, 16))
.unwrap()
.into_iter(),
);
assert_eq!(got, vec![(p(0x0a010100, 24), 3)]);
}
#[test]
fn diff_mut_find_lpm_value_does_not_require_clone() {
let mut a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a010100, 24, 3)]);
let b = map_from(&[(0x0a010100, 24, 30)]);
let got = (&mut a)
.view()
.difference(b.view())
.find_lpm_value(&p(0x0a010180, 25))
.map(|(prefix, value)| {
*value += 10;
(prefix, *value)
});
assert_eq!(got, Some((p(0x0a010000, 16), 12)));
assert_eq!(a.get(&p(0x0a010000, 16)), Some(&12));
}
#[test]
fn diff_right_shallower_navigated_to_left() {
let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a020000, 16, 3)]);
let b = map_from(&[
(0x0a000000, 8, 10),
(0x0a010000, 16, 20),
(0x0b000000, 8, 30), ]);
let a_sub = a.view_at(&p(0x0a000000, 8)).unwrap(); let b_root = b.view();
let got = collect_diff(a_sub.difference(b_root).into_iter());
assert_eq!(got, vec![(p(0x0a020000, 16), 3)]);
}
#[test]
fn diff_right_shallower_diverges() {
let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
let b = map_from(&[
(0x0b000000, 8, 10), (0x0c000000, 8, 20),
]);
let a_sub = a.view_at(&p(0x0a000000, 8)).unwrap(); let b_root = b.view();
let got = collect_diff(a_sub.difference(b_root).into_iter());
assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a010000, 16), 2),]);
}
#[test]
fn diff_left_shallower_right_deeper() {
let a = map_from(&[
(0x09000000, 8, 1),
(0x0a000000, 8, 2),
(0x0a010000, 16, 3),
(0x0b000000, 8, 4),
]);
let b = map_from(&[
(0x0a000000, 8, 10),
(0x0a010000, 16, 20),
(0x0a020000, 16, 30),
]);
let a_root = a.view();
let b_sub = b.view_at(&p(0x0a000000, 8)).unwrap();
let got = collect_diff(a_root.difference(b_sub).into_iter());
assert_eq!(
got,
vec![
(p(0x09000000, 8), 1), (p(0x0b000000, 8), 4), ]
);
}
#[test]
fn diff_left_multiple_subtries_right_covers_one() {
let a = map_from(&[
(0x0a000000, 8, 1),
(0x0a010000, 16, 2),
(0x0b000000, 8, 3),
(0x0b010000, 16, 4),
(0x0c000000, 8, 5),
]);
let b = map_from(&[
(0x0a000000, 8, 10), (0x0a010000, 16, 20), ]);
let a_root = a.view();
let b_sub = b.view_at(&p(0x0a000000, 8)).unwrap();
let got = collect_diff(a_root.difference(b_sub).into_iter());
assert_eq!(
got,
vec![
(p(0x0b000000, 8), 3), (p(0x0b010000, 16), 4),
(p(0x0c000000, 8), 5),
]
);
}
#[test]
fn diff_composed_with_intersection() {
let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0b000000, 8, 3)]);
let b = map_from(&[(0x0a000000, 8, 99)]); let c = map_from(&[(0x0a010000, 16, 100), (0x0b000000, 8, 200)]);
let got: Vec<_> = a
.view()
.difference(b.view())
.intersection(c.view())
.unwrap()
.into_iter()
.map(|(p, (l, r))| (p, *l, *r))
.collect();
assert_eq!(
got,
vec![(p(0x0a010000, 16), 2, 100), (p(0x0b000000, 8), 3, 200),]
);
}
#[test]
fn diff_composed_difference_of_differences() {
let a = map_from(&[
(0x0a000000, 8, 1),
(0x0a010000, 16, 2),
(0x0b000000, 8, 3),
(0x0c000000, 8, 4),
]);
let b = map_from(&[(0x0a000000, 8, 99)]); let c = map_from(&[(0x0b000000, 8, 99)]);
let got = collect_diff(
a.view()
.difference(b.view())
.difference(c.view())
.into_iter(),
);
assert_eq!(got, vec![(p(0x0a010000, 16), 2), (p(0x0c000000, 8), 4),]);
}
#[test]
fn view_into_right_child() {
let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 1, 1), (0x00000000, 2, 2)]);
let b = map_from(&[(0x00000000, 0, 0), (0x00000000, 2, 2)]);
let b_view = b.view_at(&p(0x00000000, 1)).unwrap();
let got = a.view().difference(b_view).iter().collect::<Vec<_>>();
let want = vec![(p(0x00000000, 0), &0), (p(0x00000000, 1), &1)];
assert_eq!(got, want);
}
#[test]
fn view_into_left_child() {
let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 1, 1), (0x00000000, 2, 2)]);
let b = map_from(&[(0x00000000, 0, 0), (0x00000000, 2, 2)]);
let a_view = a.view_at(&p(0x00000000, 1)).unwrap();
let got = a_view.difference(b.view()).iter().collect::<Vec<_>>();
let want = vec![(p(0x00000000, 1), &1)];
assert_eq!(got, want);
}
#[test]
fn view_into_right_child_deep() {
let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 5, 5), (0x00000000, 6, 6)]);
let b = map_from(&[(0x00000000, 0, 0), (0x00000000, 6, 6)]);
let b_view = b.view_at(&p(0x00000000, 5)).unwrap();
let got = a.view().difference(b_view).iter().collect::<Vec<_>>();
let want = vec![(p(0x00000000, 0), &0), (p(0x00000000, 5), &5)];
assert_eq!(got, want);
}
#[test]
fn view_into_left_child_deep() {
let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 5, 5), (0x00000000, 6, 6)]);
let b = map_from(&[(0x00000000, 0, 0), (0x00000000, 6, 6)]);
let a_view = a.view_at(&p(0x00000000, 5)).unwrap();
let got = a_view.difference(b.view()).iter().collect::<Vec<_>>();
let want = vec![(p(0x00000000, 5), &5)];
assert_eq!(got, want);
}
}