1use std::marker::PhantomData;
13
14use num_traits::PrimInt;
15
16use crate::{
17 prefix::mask_from_prefix_len,
18 Prefix,
19 {
20 node::{child_bit as node_child_bit, extend_repr},
21 table::K,
22 AsView,
23 },
24};
25
26use super::{TrieView, ViewIter};
27
28#[derive(Debug, Clone, PartialEq, Eq)]
33pub enum UnionItem<L, R> {
34 Left(L),
36 Right(R),
38 Both(L, R),
40}
41
42impl<L, R> UnionItem<L, R> {
43 pub fn left(&self) -> Option<&L> {
45 match self {
46 UnionItem::Left(l) | UnionItem::Both(l, _) => Some(l),
47 UnionItem::Right(_) => None,
48 }
49 }
50
51 pub fn right(&self) -> Option<&R> {
53 match self {
54 UnionItem::Right(r) | UnionItem::Both(_, r) => Some(r),
55 UnionItem::Left(_) => None,
56 }
57 }
58
59 pub fn both(&self) -> Option<(&L, &R)> {
61 match self {
62 UnionItem::Both(l, r) => Some((l, r)),
63 _ => None,
64 }
65 }
66
67 pub fn into_left(self) -> Option<L> {
69 match self {
70 UnionItem::Left(l) | UnionItem::Both(l, _) => Some(l),
71 UnionItem::Right(_) => None,
72 }
73 }
74
75 pub fn into_right(self) -> Option<R> {
77 match self {
78 UnionItem::Right(r) | UnionItem::Both(_, r) => Some(r),
79 UnionItem::Left(_) => None,
80 }
81 }
82
83 pub fn into_both(self) -> (Option<L>, Option<R>) {
85 match self {
86 UnionItem::Left(l) => (Some(l), None),
87 UnionItem::Right(r) => (None, Some(r)),
88 UnionItem::Both(l, r) => (Some(l), Some(r)),
89 }
90 }
91}
92
93#[derive(Clone)]
104pub struct UnionView<'a, L, R>
105where
106 L: TrieView<'a>,
107 R: TrieView<'a, P = L::P>,
108{
109 left: Option<L>,
110 right: Option<R>,
111 depth: u32,
112 key: <<L as TrieView<'a>>::P as Prefix>::R,
113 prefix_len: u32,
114 _phantom: PhantomData<&'a ()>,
115}
116
117impl<'a, L, R> UnionView<'a, L, R>
118where
119 L: TrieView<'a>,
120 R: TrieView<'a, P = L::P>,
121{
122 pub(crate) fn new(left: L, right: R) -> Self {
124 let (key, prefix_len) = common_prefix::<L::P>(
125 left.key(),
126 left.prefix_len(),
127 right.key(),
128 right.prefix_len(),
129 );
130 let depth = (prefix_len / K) * K;
131 Self {
132 left: Some(left),
133 right: Some(right),
134 depth,
135 key,
136 prefix_len,
137 _phantom: PhantomData,
138 }
139 }
140}
141
142impl<'a, L, R> TrieView<'a> for UnionView<'a, L, R>
143where
144 L: TrieView<'a>,
145 R: TrieView<'a, P = L::P>,
146{
147 type P = L::P;
148 type T = UnionItem<L::T, R::T>;
149
150 #[inline]
151 fn depth(&self) -> u32 {
152 self.depth
153 }
154
155 #[inline]
156 fn key(&self) -> <L::P as Prefix>::R {
157 self.key
158 }
159
160 #[inline]
161 fn prefix_len(&self) -> u32 {
162 self.prefix_len
163 }
164
165 #[inline]
166 fn data_bitmap(&self) -> u32 {
167 side_data_bitmap(&self.left, self.depth) | side_data_bitmap(&self.right, self.depth)
168 }
169
170 #[inline]
171 fn child_bitmap(&self) -> u32 {
172 side_child_bitmap(&self.left, self.depth) | side_child_bitmap(&self.right, self.depth)
173 }
174
175 #[inline]
176 unsafe fn get_data(&mut self, data_bit: u32) -> UnionItem<L::T, R::T> {
177 match (self.left.as_mut(), self.right.as_mut()) {
178 (Some(l), Some(r)) => {
179 if l.depth() == self.depth && r.depth() == self.depth {
180 let in_l = (l.data_bitmap() >> data_bit) & 1 == 1;
181 let in_r = (r.data_bitmap() >> data_bit) & 1 == 1;
182 match (in_l, in_r) {
183 (true, true) => UnionItem::Both(l.get_data(data_bit), r.get_data(data_bit)),
184 (true, false) => UnionItem::Left(l.get_data(data_bit)),
185 (false, true) => UnionItem::Right(r.get_data(data_bit)),
186 (false, false) => unreachable!("get_data on bit absent from data_bitmap"),
187 }
188 } else if l.depth() == self.depth {
189 UnionItem::Left(l.get_data(data_bit))
190 } else if r.depth() == self.depth {
191 UnionItem::Right(r.get_data(data_bit))
192 } else {
193 unreachable!("get_data on virtual UnionView root")
194 }
195 }
196 (Some(l), None) => UnionItem::Left(l.get_data(data_bit)),
197 (None, Some(r)) => UnionItem::Right(r.get_data(data_bit)),
198 (None, None) => unreachable!("get_data on empty UnionView"),
199 }
200 }
201
202 unsafe fn get_child(&mut self, child_bit: u32) -> Self {
203 let new_depth = self.depth + K;
204 let new_key = extend_repr(self.key, self.depth, child_bit);
205 UnionView {
206 left: take_child(&mut self.left, self.depth, child_bit),
207 right: take_child(&mut self.right, self.depth, child_bit),
208 depth: new_depth,
209 key: new_key,
210 prefix_len: new_depth,
211 _phantom: PhantomData,
212 }
213 }
214
215 unsafe fn reposition(&mut self, key: <L::P as Prefix>::R, prefix_len: u32) {
216 reposition_side(&mut self.left, self.depth, key, prefix_len);
217 reposition_side(&mut self.right, self.depth, key, prefix_len);
218 self.key = key;
219 self.prefix_len = prefix_len;
220 }
221}
222
223fn common_prefix<P: Prefix>(
224 left_key: P::R,
225 left_len: u32,
226 right_key: P::R,
227 right_len: u32,
228) -> (P::R, u32) {
229 let max_len = left_len.min(right_len);
230 let diff = (left_key & mask_from_prefix_len(max_len as u8))
231 ^ (right_key & mask_from_prefix_len(max_len as u8));
232 let len = diff.leading_zeros().min(max_len);
233 (left_key & mask_from_prefix_len(len as u8), len)
234}
235
236fn paths_overlap<P: Prefix>(
237 left_key: P::R,
238 left_len: u32,
239 right_key: P::R,
240 right_len: u32,
241) -> bool {
242 let min_len = left_len.min(right_len);
243 let mask = mask_from_prefix_len(min_len as u8);
244 left_key & mask == right_key & mask
245}
246
247fn side_data_bitmap<'a, V: TrieView<'a>>(side: &Option<V>, depth: u32) -> u32 {
248 match side {
249 Some(view) if view.depth() == depth => view.data_bitmap(),
250 _ => 0,
251 }
252}
253
254fn side_child_bitmap<'a, V: TrieView<'a>>(side: &Option<V>, depth: u32) -> u32 {
255 match side {
256 Some(view) if view.depth() == depth => view.child_bitmap(),
257 Some(view) if view.depth() > depth => 1 << node_child_bit(depth, view.key()),
258 _ => 0,
259 }
260}
261
262unsafe fn take_child<'a, V: TrieView<'a>>(
263 side: &mut Option<V>,
264 depth: u32,
265 child_bit: u32,
266) -> Option<V> {
267 let view = side.as_mut()?;
268 if view.depth() == depth {
269 if (view.child_bitmap() >> child_bit) & 1 == 1 {
270 Some(view.get_child(child_bit))
271 } else {
272 None
273 }
274 } else if view.depth() > depth {
275 if child_bit == node_child_bit(depth, view.key()) {
276 side.take()
277 } else {
278 None
279 }
280 } else {
281 None
282 }
283}
284
285unsafe fn reposition_side<'a, V: TrieView<'a>>(
286 side: &mut Option<V>,
287 union_depth: u32,
288 key: <<V as TrieView<'a>>::P as Prefix>::R,
289 prefix_len: u32,
290) {
291 let Some(view) = side.as_mut() else {
292 return;
293 };
294 if !paths_overlap::<V::P>(view.key(), view.prefix_len(), key, prefix_len) {
295 *side = None;
296 } else if view.depth() == union_depth && prefix_len >= view.prefix_len() {
297 view.reposition(key, prefix_len);
298 }
299}
300
301impl<'a, L, R> IntoIterator for UnionView<'a, L, R>
302where
303 L: TrieView<'a>,
304 R: TrieView<'a, P = L::P>,
305{
306 type Item = (L::P, UnionItem<L::T, R::T>);
307 type IntoIter = ViewIter<'a, UnionView<'a, L, R>>;
308
309 fn into_iter(self) -> Self::IntoIter {
310 self.iter()
311 }
312}
313
314impl<'a, L, R> AsView<'a> for UnionView<'a, L, R>
315where
316 L: TrieView<'a>,
317 R: TrieView<'a, P = L::P>,
318{
319 type P = L::P;
320 type View = Self;
321
322 fn view(self) -> Self {
323 self
324 }
325}
326
327#[cfg(test)]
328mod tests {
329 use crate::{
330 Prefix,
331 {
332 trieview::{AsView, TrieView},
333 PrefixMap,
334 },
335 };
336
337 use super::UnionItem;
338
339 type P = (u32, u8);
340
341 fn p(repr: u32, len: u8) -> P {
342 P::from_repr_len(repr, len)
343 }
344
345 fn map_from(entries: &[(u32, u8, i32)]) -> PrefixMap<P, i32> {
346 let mut m = PrefixMap::new();
347 for &(repr, len, val) in entries {
348 m.insert(p(repr, len), val);
349 }
350 m
351 }
352
353 fn collect_union<'a>(
354 iter: impl Iterator<Item = (P, UnionItem<&'a i32, &'a i32>)>,
355 ) -> Vec<(P, Option<i32>, Option<i32>)> {
356 iter.map(|(p, item)| match item {
357 UnionItem::Left(l) => (p, Some(*l), None),
358 UnionItem::Right(r) => (p, None, Some(*r)),
359 UnionItem::Both(l, r) => (p, Some(*l), Some(*r)),
360 })
361 .collect()
362 }
363
364 #[test]
367 fn union_disjoint() {
368 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
369 let b = map_from(&[(0x0b000000, 8, 10), (0x0b010000, 16, 20)]);
370 let got = collect_union(a.view().union(b.view()).into_iter());
371 assert_eq!(
372 got,
373 vec![
374 (p(0x0a000000, 8), Some(1), None),
375 (p(0x0a010000, 16), Some(2), None),
376 (p(0x0b000000, 8), None, Some(10)),
377 (p(0x0b010000, 16), None, Some(20)),
378 ]
379 );
380 }
381
382 #[test]
383 fn union_overlapping() {
384 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
385 let b = map_from(&[(0x0a000000, 8, 10), (0x0b000000, 8, 20)]);
386 let got = collect_union(a.view().union(b.view()).into_iter());
387 assert_eq!(
388 got,
389 vec![
390 (p(0x0a000000, 8), Some(1), Some(10)),
391 (p(0x0a010000, 16), Some(2), None),
392 (p(0x0b000000, 8), None, Some(20)),
393 ]
394 );
395 }
396
397 #[test]
398 fn union_identical() {
399 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
400 let b = map_from(&[(0x0a000000, 8, 10), (0x0a010000, 16, 20)]);
401 let got = collect_union(a.view().union(b.view()).into_iter());
402 assert_eq!(
403 got,
404 vec![
405 (p(0x0a000000, 8), Some(1), Some(10)),
406 (p(0x0a010000, 16), Some(2), Some(20)),
407 ]
408 );
409 }
410
411 #[test]
412 fn union_one_empty() {
413 let a = map_from(&[(0x0a000000, 8, 1)]);
414 let b: PrefixMap<P, i32> = PrefixMap::new();
415 let got = collect_union(a.view().union(b.view()).into_iter());
416 assert_eq!(got, vec![(p(0x0a000000, 8), Some(1), None)]);
417 }
418
419 #[test]
420 fn union_both_empty() {
421 let a: PrefixMap<P, i32> = PrefixMap::new();
422 let b: PrefixMap<P, i32> = PrefixMap::new();
423 assert!(a.view().union(b.view()).into_iter().next().is_none());
424 }
425
426 #[test]
427 fn union_into_iter_for_loop() {
428 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
429 let b = map_from(&[(0x0a000000, 8, 10), (0x0b000000, 8, 20)]);
430 let mut count = 0;
431 for (_p, _item) in a.view().union(b.view()) {
432 count += 1;
433 }
434 assert_eq!(count, 3);
435 }
436
437 #[test]
440 fn union_large_same_depth() {
441 let a = map_from(&[
442 (0x01000000, 8, 1),
443 (0x0a000000, 8, 10),
444 (0x0a010000, 16, 11),
445 (0x0a020000, 16, 12),
446 (0x0a010100, 24, 13),
447 (0x64000000, 8, 100),
448 (0x64010000, 16, 101),
449 (0xc0a80000, 16, 200), ]);
451 let b = map_from(&[
452 (0x0a000000, 8, 20), (0x0a010000, 16, 21), (0x0a030000, 16, 22), (0x0b000000, 8, 30),
456 (0x0b010000, 16, 31),
457 (0x64000000, 8, 110), (0xc0a80100, 24, 210), ]);
460 let got = collect_union(a.view().union(b.view()).into_iter());
461 assert_eq!(
462 got,
463 vec![
464 (p(0x01000000, 8), Some(1), None), (p(0x0a000000, 8), Some(10), Some(20)), (p(0x0a010000, 16), Some(11), Some(21)), (p(0x0a010100, 24), Some(13), None), (p(0x0a020000, 16), Some(12), None), (p(0x0a030000, 16), None, Some(22)), (p(0x0b000000, 8), None, Some(30)), (p(0x0b010000, 16), None, Some(31)), (p(0x64000000, 8), Some(100), Some(110)), (p(0x64010000, 16), Some(101), None), (p(0xc0a80000, 16), Some(200), None), (p(0xc0a80100, 24), None, Some(210)), ]
477 );
478 }
479
480 #[test]
481 fn union_large_same_depth_view_at() {
482 let a = map_from(&[
483 (0x01000000, 8, 1),
484 (0x0a000000, 8, 10),
485 (0x0a010000, 16, 11),
486 (0x0a020000, 16, 12),
487 (0x0a010100, 24, 13),
488 (0x64000000, 8, 100),
489 (0x64010000, 16, 101),
490 (0xc0a80000, 16, 200), ]);
492 let b = map_from(&[
493 (0x0a000000, 8, 20), (0x0a010000, 16, 21), (0x0a030000, 16, 22), (0x0b000000, 8, 30),
497 (0x0b010000, 16, 31),
498 (0x64000000, 8, 110), (0xc0a80100, 24, 210), ]);
501 let got = collect_union(
502 a.view_at(&p(0x00000000, 1))
503 .unwrap()
504 .union(b.view_at(&p(0x00000000, 1)).unwrap())
505 .into_iter(),
506 );
507 let want = vec![
508 (p(0x01000000, 8), Some(1), None), (p(0x0a000000, 8), Some(10), Some(20)), (p(0x0a010000, 16), Some(11), Some(21)), (p(0x0a010100, 24), Some(13), None), (p(0x0a020000, 16), Some(12), None), (p(0x0a030000, 16), None, Some(22)), (p(0x0b000000, 8), None, Some(30)), (p(0x0b010000, 16), None, Some(31)), (p(0x64000000, 8), Some(100), Some(110)), (p(0x64010000, 16), Some(101), None), ];
519 assert_eq!(got, want);
520 }
521
522 #[test]
523 fn union_large_different_depth() {
524 let a = map_from(&[
525 (0x01000000, 8, 1),
526 (0x0a000000, 8, 10),
527 (0x0a010000, 16, 11),
528 (0x0a020000, 16, 12),
529 (0x0a010100, 24, 13),
530 (0x64000000, 8, 100),
531 (0x64010000, 16, 101),
532 (0xc0a80000, 16, 200), ]);
534 let b = map_from(&[
535 (0x0a000000, 8, 20), (0x0a010000, 16, 21), (0x0a030000, 16, 22), (0x0b000000, 8, 30),
539 (0x0b010000, 16, 31),
540 (0x64000000, 8, 110), (0xc0a80100, 24, 210), ]);
543 let got = collect_union(
544 a.view_at(&p(0x00000000, 1))
545 .unwrap()
546 .union(b.view_at(&p(0x0a000000, 8)).unwrap())
547 .into_iter(),
548 );
549 let want = vec![
550 (p(0x01000000, 8), Some(1), None), (p(0x0a000000, 8), Some(10), Some(20)), (p(0x0a010000, 16), Some(11), Some(21)), (p(0x0a010100, 24), Some(13), None), (p(0x0a020000, 16), Some(12), None), (p(0x0a030000, 16), None, Some(22)), (p(0x64000000, 8), Some(100), None), (p(0x64010000, 16), Some(101), None), ];
559 assert_eq!(got, want);
560 }
561
562 #[test]
565 fn union_find_then_iter() {
566 let a = map_from(&[
567 (0x0a000000, 8, 1),
568 (0x0a010000, 16, 2),
569 (0x0a010100, 24, 3),
570 (0x0b000000, 8, 4),
571 ]);
572 let b = map_from(&[
573 (0x0a000000, 8, 10),
574 (0x0a010000, 16, 20),
575 (0x0a020000, 16, 30),
576 (0x0c000000, 8, 40),
577 ]);
578 let got = collect_union(
580 a.view()
581 .union(b.view())
582 .find(&p(0x0a010000, 16))
583 .unwrap()
584 .into_iter(),
585 );
586 assert_eq!(
587 got,
588 vec![
589 (p(0x0a010000, 16), Some(2), Some(20)),
590 (p(0x0a010100, 24), Some(3), None),
591 ]
592 );
593 }
594
595 #[test]
596 fn union_find_exact_and_value() {
597 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
598 let b = map_from(&[(0x0a000000, 8, 10), (0x0b000000, 8, 20)]);
599 let u = a.view().union(b.view());
600
601 let v = u.clone().find_exact(&p(0x0a000000, 8)).unwrap();
603 assert!(matches!(v.value().unwrap(), UnionItem::Both(l, r) if *l == 1 && *r == 10));
604
605 let v2 = u.clone().find_exact(&p(0x0a010000, 16)).unwrap();
607 assert!(matches!(v2.value().unwrap(), UnionItem::Left(l) if *l == 2));
608
609 let v3 = u.clone().find_exact(&p(0x0b000000, 8)).unwrap();
611 assert!(matches!(v3.value().unwrap(), UnionItem::Right(r) if *r == 20));
612
613 assert!(u.find_exact(&p(0x0c000000, 8)).is_none());
615 }
616
617 #[test]
618 fn union_find_lpm_value_keys_values() {
619 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2)]);
620 let b = map_from(&[(0x0a010100, 24, 30), (0x0b000000, 8, 40)]);
621 let u = a.view().union(b.view());
622
623 let lpm = u.clone().find_lpm(&p(0x0a010180, 25)).unwrap();
624 assert_eq!(lpm.prefix(), p(0x0a010100, 24));
625 assert!(matches!(lpm.value().unwrap(), UnionItem::Right(r) if *r == 30));
626
627 let got = u
628 .clone()
629 .find_lpm_value(&p(0x0a010180, 25))
630 .map(|(prefix, value)| (prefix, value.into_both()));
631 assert!(matches!(
632 got,
633 Some((prefix, (None, Some(r)))) if prefix == p(0x0a010100, 24) && *r == 30
634 ));
635
636 assert_eq!(
637 u.clone().keys().collect::<Vec<_>>(),
638 vec![
639 p(0x0a000000, 8),
640 p(0x0a010000, 16),
641 p(0x0a010100, 24),
642 p(0x0b000000, 8),
643 ]
644 );
645 assert_eq!(u.values().count(), 4);
646 }
647
648 #[test]
649 fn union_mut_find_lpm_value_does_not_require_clone() {
650 let mut a = map_from(&[(0x0a000000, 8, 1), (0x0a010100, 24, 3)]);
651 let b = map_from(&[(0x0a000000, 8, 10), (0x0a010000, 16, 20)]);
652
653 let got = (&mut a)
654 .view()
655 .union(b.view())
656 .find_lpm_value(&p(0x0a010180, 25))
657 .map(|(prefix, item)| match item {
658 UnionItem::Left(l) => {
659 *l += 10;
660 (prefix, *l)
661 }
662 other => panic!("expected left-only LPM, got {other:?}"),
663 });
664
665 assert_eq!(got, Some((p(0x0a010100, 24), 13)));
666 assert_eq!(a.get(&p(0x0a010100, 24)), Some(&13));
667 }
668
669 #[test]
685 fn union_l_deeper_r_shallower_going_toward_and_not() {
686 let a = map_from(&[
687 (0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a020000, 16, 3), ]);
691 let b = map_from(&[
692 (0x09000000, 8, 90), (0x0a000000, 8, 10), (0x0a010000, 16, 20), (0x0b000000, 8, 30), ]);
697 let a_sub = a.view_at(&p(0x0a000000, 8)).unwrap(); let b_root = b.view(); let got = collect_union(a_sub.union(b_root).into_iter());
701 assert_eq!(
702 got,
703 vec![
704 (p(0x09000000, 8), None, Some(90)), (p(0x0a000000, 8), Some(1), Some(10)), (p(0x0a010000, 16), Some(2), Some(20)), (p(0x0a020000, 16), Some(3), None), (p(0x0b000000, 8), None, Some(30)), ]
710 );
711 }
712
713 #[test]
716 fn union_r_deeper_l_shallower_going_toward_and_not() {
717 let a = map_from(&[
718 (0x09000000, 8, 90),
719 (0x0a000000, 8, 10),
720 (0x0a010000, 16, 20),
721 (0x0b000000, 8, 30),
722 ]);
723 let b = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a020000, 16, 3)]);
724 let a_root = a.view();
725 let b_sub = b.view_at(&p(0x0a000000, 8)).unwrap(); let got = collect_union(a_root.union(b_sub).into_iter());
728 assert_eq!(
729 got,
730 vec![
731 (p(0x09000000, 8), Some(90), None), (p(0x0a000000, 8), Some(10), Some(1)), (p(0x0a010000, 16), Some(20), Some(2)),
734 (p(0x0a020000, 16), None, Some(3)), (p(0x0b000000, 8), Some(30), None), ]
737 );
738 }
739
740 #[test]
744 fn union_shallower_has_no_child_toward_deeper() {
745 let a = map_from(&[
748 (0x09000000, 8, 1), (0x0b000000, 8, 2), ]);
751 let b = map_from(&[
752 (0x0a000000, 8, 10), (0x0a010000, 16, 20), (0x0a010100, 24, 30), ]);
756 let a_root = a.view();
757 let b_sub = b.view_at(&p(0x0a000000, 8)).unwrap(); let got = collect_union(a_root.union(b_sub).into_iter());
760 assert_eq!(
761 got,
762 vec![
763 (p(0x09000000, 8), Some(1), None), (p(0x0a000000, 8), None, Some(10)), (p(0x0a010000, 16), None, Some(20)), (p(0x0a010100, 24), None, Some(30)), (p(0x0b000000, 8), Some(2), None), ]
769 );
770 }
771
772 #[test]
775 fn union_shallower_multiple_children_only_one_toward_deeper() {
776 let a = map_from(&[
780 (0x0a000000, 8, 1),
781 (0x0a010000, 16, 2),
782 (0x0b000000, 8, 3),
783 (0x0c000000, 8, 4),
784 ]);
785 let b = map_from(&[
786 (0x0a000000, 8, 10),
787 (0x0a020000, 16, 20), ]);
789 let a_root = a.view();
790 let b_sub = b.view_at(&p(0x0a000000, 8)).unwrap(); let got = collect_union(a_root.union(b_sub).into_iter());
793 assert_eq!(
794 got,
795 vec![
796 (p(0x0a000000, 8), Some(1), Some(10)), (p(0x0a010000, 16), Some(2), None), (p(0x0a020000, 16), None, Some(20)), (p(0x0b000000, 8), Some(3), None), (p(0x0c000000, 8), Some(4), None), ]
802 );
803 }
804
805 #[test]
809 fn union_multi_level_depth_difference() {
810 let a = map_from(&[
814 (0x0a010000, 16, 1), (0x0a010100, 24, 2), (0x0a010200, 24, 3), ]);
818 let b = map_from(&[
819 (0x0a000000, 8, 10), (0x0a010000, 16, 20), (0x0b000000, 8, 30), ]);
823 let a_sub = a.view_at(&p(0x0a010000, 16)).unwrap(); let b_root = b.view(); let got = collect_union(a_sub.union(b_root).into_iter());
827 assert_eq!(
828 got,
829 vec![
830 (p(0x0a000000, 8), None, Some(10)), (p(0x0a010000, 16), Some(1), Some(20)), (p(0x0a010100, 24), Some(2), None), (p(0x0a010200, 24), Some(3), None), (p(0x0b000000, 8), None, Some(30)), ]
836 );
837 }
838
839 #[test]
842 fn union_composed_with_intersection() {
843 let a = map_from(&[(0x0a000000, 8, 1), (0x0b000000, 8, 2)]);
845 let b = map_from(&[(0x0a000000, 8, 10), (0x0c000000, 8, 20)]);
846 let c = map_from(&[(0x0a000000, 8, 100)]);
847
848 let got: Vec<_> = a
849 .view()
850 .union(&b)
851 .intersection(&c)
852 .unwrap()
853 .into_iter()
854 .map(|(p, (u, r))| (p, u, *r))
855 .collect();
856 assert_eq!(got.len(), 1);
857 assert_eq!(got[0].0, p(0x0a000000, 8));
858 assert_eq!(got[0].2, 100);
859 assert!(matches!(got[0].1, UnionItem::Both(l, r) if *l == 1 && *r == 10));
860 }
861
862 #[test]
863 fn union_composed_union_of_unions() {
864 let a = map_from(&[(0x0a000000, 8, 1)]);
866 let b = map_from(&[(0x0b000000, 8, 2)]);
867 let c = map_from(&[(0x0c000000, 8, 3), (0x0a000000, 8, 10)]);
868
869 let count = a.view().union(b.view()).union(c.view()).into_iter().count();
870 assert_eq!(count, 3);
872 }
873
874 #[test]
877 fn union_iter_from_inclusive() {
878 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a020000, 16, 3)]);
879 let b = map_from(&[(0x0a010000, 16, 20), (0x0a030000, 16, 40)]);
880
881 let u = a.view().union(b.view());
883 let from: Vec<_> = u
884 .iter_from(&p(0x0a010000, 16), true)
885 .map(|(p, _)| p)
886 .collect();
887 assert_eq!(
888 from,
889 vec![p(0x0a010000, 16), p(0x0a020000, 16), p(0x0a030000, 16)]
890 );
891 }
892
893 #[test]
894 fn union_iter_from_exclusive() {
895 let a = map_from(&[(0x0a000000, 8, 1), (0x0a010000, 16, 2), (0x0a020000, 16, 3)]);
896 let b = map_from(&[(0x0a010000, 16, 20), (0x0a030000, 16, 40)]);
897
898 let u = a.view().union(b.view());
899 let from: Vec<_> = u
900 .iter_from(&p(0x0a010000, 16), false)
901 .map(|(p, _)| p)
902 .collect();
903 assert_eq!(from, vec![p(0x0a020000, 16), p(0x0a030000, 16)]);
904 }
905
906 #[test]
907 fn union_iter_from_subview() {
908 let a = map_from(&[
909 (0x0a000000, 8, 1), (0x0a020000, 16, 2),
911 (0x0a030000, 16, 3),
912 (0x0b000000, 8, 4), ]);
914 let b = map_from(&[
915 (0x0a020000, 16, 20),
916 (0x0a030000, 16, 40),
917 (0x0b000000, 8, 50), ]);
919
920 let u = a
922 .view_at(&p(0x0a020000, 15))
923 .unwrap()
924 .union(b.view_at(&p(0x0a020000, 15)).unwrap());
925
926 let all: Vec<_> = u.clone().iter().map(|(p, _)| p).collect();
928 assert_eq!(all, vec![p(0x0a020000, 16), p(0x0a030000, 16)]);
929
930 let from: Vec<_> = u
932 .iter_from(&p(0x0a020000, 16), false)
933 .map(|(p, _)| p)
934 .collect();
935 assert_eq!(from, vec![p(0x0a030000, 16)]);
936 }
937}