Skip to main content

prefix_trie/trieview/
covering_difference.rs

1//! Covering-difference set-operation view: L minus entries covered by R.
2//!
3//! [`CoveringDifferenceView`] yields every prefix present in the left view for which there
4//! is no *covering* prefix in the right view. A prefix `P_r` in R covers `P_l` in L iff
5//! `P_r.len ≤ P_l.len` and `P_r` matches the leading bits of `P_l` (i.e. `P_r` is an
6//! ancestor of, or exactly equal to, `P_l`).
7//!
8//! ## Intra-node coverage
9//!
10//! For each set bit `r_b` in R's data bitmap, `data_cover_mask_for_bit` and
11//! `child_cover_mask_for_bit` give the data and child slots it covers within the node.
12//! The unions of these masks are precomputed once (in `new` / `get_child`) into `cov_data`
13//! and `cov_child`, making `data_bitmap` / `child_bitmap` O(1) bitwise operations.
14//!
15//! ## Depth handling
16//!
17//! - **Right shallower**: navigated step-by-step toward left's depth, checking at each
18//!   intermediate node whether R has an ancestor (via `data_lpm_mask`) that covers all
19//!   of L's subtrie. If found the entire subtrie is marked as covered.
20//! - **Right same depth**: coverage precomputed at construction / `get_child`.
21//! - **Right deeper**: carried along until left's traversal reaches right's depth.
22
23use std::marker::PhantomData;
24
25use crate::{
26    prefix::mask_from_prefix_len,
27    Prefix,
28    {
29        node::{
30            child_bit as node_child_bit, child_cover_mask_for_bit, data_cover_mask_for_bit,
31            data_lpm_mask,
32        },
33        AsView,
34    },
35};
36
37use super::{iter::ViewIter, TrieView};
38
39/// An immutable view over the covering difference of two [`TrieView`]s.
40///
41/// Returned by [`TrieView::covering_difference`]. Iterates over every prefix `P_l`
42/// in the left view for which there is no prefix `P_r` in the right view satisfying
43/// `P_r.len ≤ P_l.len` and `P_r` matching `P_l`'s leading bits.
44///
45/// Coverage is encoded directly in `cov_data` / `cov_child`: **a set bit means that L
46/// slot is covered by R and must not be yielded**. `data_bitmap` and `child_bitmap` are
47/// computed as `left_bitmap & !cov_bitmap`. The special case where an ancestor R covers
48/// the entire subtrie is represented by `cov_data = 0x7FFFFFFF, cov_child = 0xFFFFFFFF`
49/// (all 31 data bits and all 32 child bits), which drives both bitmaps to zero.
50#[derive(Clone)]
51pub struct CoveringDifferenceView<'a, L, R> {
52    left: L,
53    right: Option<R>,
54    /// Mask of data bits covered by R. **A set bit is excluded from `data_bitmap`.**
55    /// `0` means nothing is covered (all left data bits may be yielded).
56    /// `0x7FFFFFFF` means the entire subtrie is covered (nothing yielded).
57    cov_data: u32,
58    /// Mask of child bits covered by R. **A set bit is excluded from `child_bitmap`.**
59    /// `0` means nothing is covered; `0xFFFFFFFF` means all children are covered.
60    cov_child: u32,
61    _phantom: PhantomData<&'a ()>,
62}
63
64impl<'a, L, R> CoveringDifferenceView<'a, L, R>
65where
66    L: TrieView<'a>,
67    R: TrieView<'a, P = L::P>,
68{
69    pub(crate) fn new(left: L, right: R) -> Self {
70        let (right, covered) = align_right(&left, right);
71        let (cov_data, cov_child) = r_coverage_masks(&left, right.as_ref(), covered);
72        Self {
73            left,
74            right,
75            cov_data,
76            cov_child,
77            _phantom: PhantomData,
78        }
79    }
80}
81
82/// Align right toward left's position, checking for covering ancestors along the way.
83///
84/// Returns `(Some(r), false)` when aligned without finding a covering ancestor,
85/// `(None, false)` when right has no path to left's subtrie, and `(None, true)` when
86/// a covering ancestor in right was found (the entire L subtrie must be excluded).
87fn align_right<'a, L, R>(left: &L, mut right: R) -> (Option<R>, bool)
88where
89    L: TrieView<'a>,
90    R: TrieView<'a, P = L::P>,
91{
92    let min_prefix_len = left.prefix_len().min(right.prefix_len());
93    let mask = mask_from_prefix_len(min_prefix_len as u8);
94    if left.key() & mask != right.key() & mask {
95        return (None, false); // diverging keys -> no overlap
96    }
97
98    match right.depth().cmp(&left.depth()) {
99        std::cmp::Ordering::Greater => (Some(right), false),
100        std::cmp::Ordering::Equal => (Some(right), false),
101        std::cmp::Ordering::Less => {
102            // Navigate right toward left one K-level at a time, checking at each node
103            // whether R has an ancestor that covers all of L's subtrie.
104            loop {
105                // data_lpm_mask gives data bits in this node that are ancestors of
106                // (left.key(), left.depth). If any are set in R, L's subtrie is covered.
107                let lpm = data_lpm_mask(right.depth(), left.key(), left.depth());
108                if right.data_bitmap() & lpm != 0 {
109                    return (None, true);
110                }
111                if right.depth() == left.depth() {
112                    return (Some(right), false);
113                }
114                let cb = node_child_bit(right.depth(), left.key());
115                if (right.child_bitmap() >> cb) & 1 == 0 {
116                    return (None, false);
117                }
118                // SAFETY: we are replacing right with that child; won't call get_child on the old
119                // right ever again (and didn't do so yet)
120                right = unsafe { right.get_child(cb) };
121            }
122        }
123    }
124}
125
126/// Compute the coverage masks from R's data bitmap.
127///
128/// **A set bit in the returned masks means that the corresponding L data/child slot is
129/// covered by R and must be excluded from iteration.**
130///
131/// - If `covered` is `true` (an R ancestor covers the entire subtrie), returns
132///   `(0x7FFFFFFF, 0xFFFFFFFF)` -> all 31 data bits and all 32 child bits set, so that
133///   `left_bitmap & !cov` drives both effective bitmaps to zero.
134/// - If `right` is `None` or at a greater depth than `left` (no intra-node coverage
135///   applies yet), returns `(0, 0)` -> nothing is covered, all left entries are kept.
136/// - Otherwise iterates each set bit in `right.data_bitmap()` and ORs in the data and
137///   child slots it covers via [`data_cover_mask_for_bit`] / [`child_cover_mask_for_bit`].
138fn r_coverage_masks<'a, L, R>(left: &L, right: Option<&R>, covered: bool) -> (u32, u32)
139where
140    L: TrieView<'a>,
141    R: TrieView<'a, P = L::P>,
142{
143    if covered {
144        return (0x7FFF_FFFF, 0xFFFF_FFFF);
145    }
146    let Some(r) = right else { return (0, 0) };
147    if r.depth() != left.depth() {
148        return (0, 0);
149    }
150    let mut cov_data = 0u32;
151    let mut cov_child = 0u32;
152    let mut bits = r.data_bitmap();
153    while bits != 0 {
154        let r_b = bits.trailing_zeros();
155        bits &= bits - 1;
156        cov_data |= data_cover_mask_for_bit(r_b);
157        cov_child |= child_cover_mask_for_bit(r_b);
158    }
159    (cov_data, cov_child)
160}
161
162impl<'a, L, R> TrieView<'a> for CoveringDifferenceView<'a, L, R>
163where
164    L: TrieView<'a>,
165    R: TrieView<'a, P = L::P>,
166{
167    type P = L::P;
168    type T = L::T;
169
170    #[inline]
171    fn depth(&self) -> u32 {
172        self.left.depth()
173    }
174
175    #[inline]
176    fn key(&self) -> <L::P as Prefix>::R {
177        self.left.key()
178    }
179
180    #[inline]
181    fn prefix_len(&self) -> u32 {
182        self.left.prefix_len()
183    }
184
185    /// Effective data bitmap: left's bitmap minus any bits covered by R.
186    ///
187    /// When the entire subtrie is covered (`cov_data = 0x7FFFFFFF`), this returns 0
188    /// because `left.data_bitmap()` only uses bits 0-30 and `!0x7FFFFFFF = 0x80000000`.
189    #[inline]
190    fn data_bitmap(&self) -> u32 {
191        self.left.data_bitmap() & !self.cov_data
192    }
193
194    /// Effective child bitmap: left's bitmap minus any children fully covered by R.
195    ///
196    /// When the entire subtrie is covered (`cov_child = 0xFFFFFFFF`), this returns 0.
197    #[inline]
198    fn child_bitmap(&self) -> u32 {
199        self.left.child_bitmap() & !self.cov_child
200    }
201
202    #[inline]
203    unsafe fn get_data(&mut self, data_bit: u32) -> L::T {
204        self.left.get_data(data_bit)
205    }
206
207    unsafe fn get_child(&mut self, child_bit: u32) -> Self {
208        let l_child = self.left.get_child(child_bit);
209        let r_child = match &mut self.right {
210            None => None,
211            Some(r) => {
212                if r.depth() == self.left.depth() {
213                    if (r.child_bitmap() >> child_bit) & 1 == 1 {
214                        Some(r.get_child(child_bit))
215                    } else {
216                        None
217                    }
218                } else {
219                    // R is deeper -> carry it along only if this child leads toward R.
220                    let toward_r = node_child_bit(self.left.depth(), r.key());
221                    if child_bit == toward_r {
222                        Some(self.right.take().unwrap())
223                    } else {
224                        None
225                    }
226                }
227            }
228        };
229        let (cov_data, cov_child) = r_coverage_masks(&l_child, r_child.as_ref(), false);
230        CoveringDifferenceView {
231            left: l_child,
232            right: r_child,
233            cov_data,
234            cov_child,
235            _phantom: PhantomData,
236        }
237    }
238
239    unsafe fn reposition(&mut self, key: <L::P as Prefix>::R, prefix_len: u32) {
240        let left_depth = self.left.depth();
241        unsafe {
242            self.left.reposition(key, prefix_len);
243            if let Some(r) = self.right.as_mut() {
244                if r.depth() == left_depth {
245                    r.reposition(key, prefix_len)
246                }
247            }
248        }
249    }
250}
251
252impl<'a, L, R> IntoIterator for CoveringDifferenceView<'a, L, R>
253where
254    L: TrieView<'a>,
255    R: TrieView<'a, P = L::P>,
256{
257    type Item = (L::P, L::T);
258    type IntoIter = ViewIter<'a, CoveringDifferenceView<'a, L, R>>;
259
260    fn into_iter(self) -> Self::IntoIter {
261        self.iter()
262    }
263}
264
265impl<'a, L, R> AsView<'a> for CoveringDifferenceView<'a, L, R>
266where
267    L: TrieView<'a>,
268    R: TrieView<'a, P = L::P>,
269{
270    type P = L::P;
271    type View = Self;
272
273    fn view(self) -> Self {
274        self
275    }
276}
277
278#[cfg(test)]
279mod tests {
280    use crate::{
281        Prefix,
282        {
283            trieview::{AsView, TrieView},
284            PrefixMap,
285        },
286    };
287
288    type P = (u32, u8);
289
290    fn p(repr: u32, len: u8) -> P {
291        P::from_repr_len(repr, len)
292    }
293
294    fn map_from(entries: &[(u32, u8, i32)]) -> PrefixMap<P, i32> {
295        let mut m = PrefixMap::new();
296        for &(repr, len, val) in entries {
297            m.insert(p(repr, len), val);
298        }
299        m
300    }
301
302    fn collect<'a>(iter: impl Iterator<Item = (P, &'a i32)>) -> Vec<(P, i32)> {
303        iter.map(|(p, v)| (p, *v)).collect()
304    }
305
306    // -- Same-depth tests ------------------------------------------------------
307
308    /// Basic: R has a shorter prefix that covers some L entries.
309    ///
310    /// A = {/22=1, /24=2, /23_2=3}, B = {/23}
311    ///   - /24 is covered by /23 in B -> excluded
312    ///   - /22 is shorter than /23 -> kept
313    ///   - /23_2 (different subtrie) -> kept
314    #[test]
315    fn covering_diff_basic() {
316        let a = map_from(&[
317            (0x0a000000, 22, 1), // 10.0.0.0/22
318            (0x0a000000, 24, 2), // 10.0.0.0/24 -> covered by /23
319            (0x0a000200, 23, 3), // 10.0.2.0/23 -> different /23, not covered
320        ]);
321        let b = map_from(&[(0x0a000000, 23, 99)]); // 10.0.0.0/23
322        let got = collect(a.view().covering_difference(b.view()).into_iter());
323        assert_eq!(got, vec![(p(0x0a000000, 22), 1), (p(0x0a000200, 23), 3),]);
324    }
325
326    /// R has no overlap with L -> all L entries kept.
327    #[test]
328    fn covering_diff_no_overlap() {
329        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
330        let b = map_from(&[(0x0b000000, 8, 99)]);
331        let got = collect(a.view().covering_difference(b.view()).into_iter());
332        assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a010000, 16), 2),]);
333    }
334
335    /// R has exact same prefix as an L entry -> excluded (same = covered).
336    #[test]
337    fn covering_diff_exact_match_excluded() {
338        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a020000, 16, 3)]);
339        let b = map_from(&[(0x0a010000, 16, 99)]);
340        let got = collect(a.view().covering_difference(b.view()).into_iter());
341        assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a020000, 16), 3),]);
342    }
343
344    /// R's covering prefix covers all L entries in the overlapping subtrie.
345    #[test]
346    fn covering_diff_r_covers_everything() {
347        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
348        let b = map_from(&[(0x0a000000, 8, 99)]);
349        assert!(a
350            .view()
351            .covering_difference(b.view())
352            .into_iter()
353            .next()
354            .is_none());
355    }
356
357    /// R is empty -> all L entries kept.
358    #[test]
359    fn covering_diff_r_empty() {
360        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
361        let b: PrefixMap<P, i32> = PrefixMap::new();
362        let got = collect(a.view().covering_difference(b.view()).into_iter());
363        assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a010000, 16), 2),]);
364    }
365
366    /// L is empty -> result is empty.
367    #[test]
368    fn covering_diff_l_empty() {
369        let a: PrefixMap<P, i32> = PrefixMap::new();
370        let b = map_from(&[(0x0a000000, 8, 99)]);
371        assert!(a
372            .view()
373            .covering_difference(b.view())
374            .into_iter()
375            .next()
376            .is_none());
377    }
378
379    /// R covers part of L's entries via a shorter prefix; deeper entries are excluded.
380    #[test]
381    fn covering_diff_partial_coverage() {
382        let a = map_from(&[
383            (0x0a000000, 8, 1),
384            (0x0a010000, 16, 2),
385            (0x0a010100, 24, 3), // covered by 10.1/16 in b
386            (0x0a020000, 16, 4),
387            (0x0b000000, 8, 5),
388        ]);
389        let b = map_from(&[(0x0a010000, 16, 99)]);
390        let got = collect(a.view().covering_difference(b.view()).into_iter());
391        assert_eq!(
392            got,
393            vec![
394                (p(0x0a000000, 8), 1),
395                // 10.1/16 excluded (exact match)
396                // 10.1.1/24 excluded (covered by 10.1/16)
397                (p(0x0a020000, 16), 4),
398                (p(0x0b000000, 8), 5),
399            ]
400        );
401    }
402
403    /// Large same-depth test with multiple subtries.
404    #[test]
405    fn covering_diff_large_same_depth() {
406        let a = map_from(&[
407            (0x01000000, 8, 1),
408            (0x0a000000, 8, 10),
409            (0x0a000000, 16, 11),
410            (0x0a010000, 16, 12),
411            (0x0a010100, 24, 13),
412            (0x0a020000, 16, 14),
413            (0x0b000000, 8, 20),
414            (0x0b010000, 16, 21),
415            (0x64000000, 8, 100),
416        ]);
417        let b = map_from(&[
418            (0x0a000000, 8, 99),  // covers all 10.x entries
419            (0x0b010000, 16, 99), // covers 11.1/16
420        ]);
421        let got = collect(a.view().covering_difference(b.view()).into_iter());
422        assert_eq!(
423            got,
424            vec![
425                (p(0x01000000, 8), 1),
426                // all 10.x entries excluded
427                (p(0x0b000000, 8), 20),
428                // 11.1/16 excluded
429                (p(0x64000000, 8), 100),
430            ]
431        );
432    }
433
434    // -- find / find_lpm --------------------------------------------------------
435
436    #[test]
437    fn covering_diff_find_then_iter() {
438        let a = map_from(&[
439            (0x0a000000, 8, 1),
440            (0x0a010000, 16, 2),
441            (0x0a010100, 24, 3), // covered
442            (0x0a020000, 16, 4),
443        ]);
444        let b = map_from(&[(0x0a010000, 16, 99)]);
445        let sub = a
446            .view()
447            .covering_difference(b.view())
448            .find(&p(0x0a000000, 8));
449        assert!(sub.is_some());
450        let got = collect(sub.unwrap().into_iter());
451        assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a020000, 16), 4),]);
452    }
453
454    #[test]
455    fn covering_diff_mut_find_lpm_value_does_not_require_clone() {
456        let mut a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a010100, 24, 3)]);
457        let b = map_from(&[(0x0a010100, 24, 30)]);
458
459        let got = (&mut a)
460            .view()
461            .covering_difference(b.view())
462            .find_lpm_value(&p(0x0a010180, 25))
463            .map(|(prefix, value)| {
464                *value += 10;
465                (prefix, *value)
466            });
467
468        assert_eq!(got, Some((p(0x0a010000, 16), 12)));
469        assert_eq!(a.get(&p(0x0a010000, 16)), Some(&12));
470    }
471
472    // -- Depth-difference cases ------------------------------------------------
473
474    /// Right shallower, has a covering ancestor found during navigation -> all excluded.
475    #[test]
476    fn covering_diff_right_shallower_covers() {
477        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
478        let b = map_from(&[(0x0a000000, 8, 99)]);
479        let a_sub = a.view_at(&p(0x0a000000, 8)).unwrap();
480        let b_root = b.view();
481        assert!(a_sub
482            .covering_difference(b_root)
483            .into_iter()
484            .next()
485            .is_none());
486    }
487
488    /// Right shallower but has no covering prefix along the path -> all kept.
489    #[test]
490    fn covering_diff_right_shallower_no_cover() {
491        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
492        let b = map_from(&[(0x0b000000, 8, 99)]);
493        let a_sub = a.view_at(&p(0x0a000000, 8)).unwrap();
494        let b_root = b.view();
495        let got = collect(a_sub.covering_difference(b_root).into_iter());
496        assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a010000, 16), 2),]);
497    }
498
499    /// Right shallower, navigates to left's depth with partial coverage.
500    #[test]
501    fn covering_diff_right_shallower_partial() {
502        let a = map_from(&[
503            (0x0a000000, 8, 1),
504            (0x0a010000, 16, 2), // will be covered
505            (0x0a020000, 16, 3),
506        ]);
507        let b = map_from(&[(0x0a010000, 16, 99), (0x0b000000, 8, 99)]);
508        let a_sub = a.view_at(&p(0x0a000000, 8)).unwrap();
509        let b_root = b.view();
510        let got = collect(a_sub.covering_difference(b_root).into_iter());
511        assert_eq!(got, vec![(p(0x0a000000, 8), 1), (p(0x0a020000, 16), 3),]);
512    }
513
514    /// Left shallower than right: entries not toward R's subtrie are kept entirely.
515    /// R's /16 doesn't cover L's /8 (shorter prefix).
516    #[test]
517    fn covering_diff_left_shallower_right_deeper() {
518        let a = map_from(&[
519            (0x09000000, 8, 1),
520            (0x0a000000, 8, 2),
521            (0x0a010000, 16, 3), // exact match in b_sub -> excluded
522            (0x0b000000, 8, 4),
523        ]);
524        let b = map_from(&[(0x0a010000, 16, 99)]);
525        let a_root = a.view();
526        let b_sub = b.view_at(&p(0x0a010000, 16)).unwrap();
527        let got = collect(a_root.covering_difference(b_sub).into_iter());
528        assert_eq!(
529            got,
530            vec![
531                (p(0x09000000, 8), 1),
532                (p(0x0a000000, 8), 2), // kept: /8 is shorter than b_sub's /16
533                // 10.1/16 excluded
534                (p(0x0b000000, 8), 4),
535            ]
536        );
537    }
538
539    // -- Composition -----------------------------------------------------------
540
541    #[test]
542    fn covering_diff_composed_with_difference() {
543        let a = map_from(&[
544            (0x0a000000, 8, 1),
545            (0x0a010000, 16, 2),
546            (0x0a010100, 24, 3), // covered
547            (0x0b000000, 8, 4),
548        ]);
549        let b = map_from(&[(0x0a010000, 16, 99)]);
550        let c = map_from(&[(0x0a000000, 8, 99)]);
551
552        // covering_diff = {10/8, 11/8}; diff c removes 10/8
553        let got = collect(
554            a.view()
555                .covering_difference(b.view())
556                .difference(c.view())
557                .into_iter(),
558        );
559        assert_eq!(got, vec![(p(0x0b000000, 8), 4)]);
560    }
561
562    #[test]
563    fn covering_diff_composed_with_intersection() {
564        let a = map_from(&[
565            (0x0a000000, 8, 1),
566            (0x0a010000, 16, 2),
567            (0x0a010100, 24, 3), // covered
568            (0x0b000000, 8, 4),
569        ]);
570        let b = map_from(&[(0x0a010000, 16, 99)]);
571        let c = map_from(&[(0x0a000000, 8, 100), (0x0b000000, 8, 200)]);
572
573        // covering_diff = {10/8, 11/8}; ∩ c = {10/8, 11/8}
574        let got: Vec<_> = a
575            .view()
576            .covering_difference(b.view())
577            .intersection(c.view())
578            .unwrap()
579            .into_iter()
580            .map(|(p, (l, r))| (p, *l, *r))
581            .collect();
582        assert_eq!(
583            got,
584            vec![(p(0x0a000000, 8), 1, 100), (p(0x0b000000, 8), 4, 200),]
585        );
586    }
587
588    #[test]
589    fn covering_diff_into_iter_for_loop() {
590        let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
591        let b = map_from(&[(0x0a010000, 16, 99)]);
592        let mut count = 0;
593        for _ in a.view().covering_difference(b.view()) {
594            count += 1;
595        }
596        assert_eq!(count, 1); // only 10/8 kept
597    }
598
599    #[test]
600    fn view_into_right_child() {
601        let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 1, 1), (0x00000000, 2, 2)]);
602        let b = map_from(&[(0x00000000, 0, 0), (0x00000000, 2, 2)]);
603        let b_view = b.view_at(&p(0x00000000, 1)).unwrap();
604        let got = a
605            .view()
606            .covering_difference(b_view)
607            .iter()
608            .collect::<Vec<_>>();
609        let want = vec![(p(0x00000000, 0), &0), (p(0x00000000, 1), &1)];
610        assert_eq!(got, want);
611    }
612
613    #[test]
614    fn view_into_left_child() {
615        let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 1, 1), (0x00000000, 2, 2)]);
616        let b = map_from(&[(0x00000000, 2, 2)]);
617        let a_view = a.view_at(&p(0x00000000, 1)).unwrap();
618        let got = a_view
619            .covering_difference(b.view())
620            .iter()
621            .collect::<Vec<_>>();
622        let want = vec![(p(0x00000000, 1), &1)];
623        assert_eq!(got, want);
624    }
625
626    #[test]
627    fn view_into_right_child_deep() {
628        let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 5, 5), (0x00000000, 6, 6)]);
629        let b = map_from(&[(0x00000000, 0, 0), (0x00000000, 6, 6)]);
630        let b_view = b.view_at(&p(0x00000000, 5)).unwrap();
631        let got = a
632            .view()
633            .covering_difference(b_view)
634            .iter()
635            .collect::<Vec<_>>();
636        let want = vec![(p(0x00000000, 0), &0), (p(0x00000000, 5), &5)];
637        assert_eq!(got, want);
638    }
639
640    #[test]
641    fn view_into_left_child_deep() {
642        let a = map_from(&[(0x00000000, 0, 0), (0x00000000, 5, 5), (0x00000000, 6, 6)]);
643        let b = map_from(&[(0x00000000, 6, 6)]);
644        let a_view = a.view_at(&p(0x00000000, 5)).unwrap();
645        let got = a_view
646            .covering_difference(b.view())
647            .iter()
648            .collect::<Vec<_>>();
649        let want = vec![(p(0x00000000, 5), &5)];
650        assert_eq!(got, want);
651    }
652}