splinter_rs/splinter/
cut.rs1use crate::{bitmap::BitmapExt, cow::CowSplinter, ops::Cut, relational::Relation};
2
3use super::{Splinter, SplinterRef};
4
5impl Cut for Splinter {
6 type Output = Splinter;
7
8 fn cut(&mut self, rhs: &Self) -> Self::Output {
9 let mut out = Splinter::default();
10
11 let rhs = &rhs.partitions;
12 self.partitions.retain(|&a, left| {
13 if let Some(right) = rhs.get(a) {
14 left.retain(|&b, left| {
16 if let Some(right) = right.get(b) {
17 left.retain(|&c, left| {
19 if let Some(right) = right.get(c) {
20 out.insert_block(a, b, c, left.cut(right));
21 left.has_bits_set()
22 } else {
23 true
24 }
25 });
26 !left.is_empty()
27 } else {
28 true
29 }
30 });
31 !left.is_empty()
32 } else {
33 true
34 }
35 });
36
37 out
38 }
39}
40
41impl<T: AsRef<[u8]>> Cut<SplinterRef<T>> for Splinter {
42 type Output = Splinter;
43
44 fn cut(&mut self, rhs: &SplinterRef<T>) -> Self::Output {
45 let mut out = Splinter::default();
46
47 let rhs = rhs.load_partitions();
48 self.partitions.retain(|&a, left| {
49 if let Some(right) = rhs.get(a) {
50 left.retain(|&b, left| {
52 if let Some(right) = right.get(b) {
53 left.retain(|&c, left| {
55 if let Some(right) = right.get(c) {
56 out.insert_block(a, b, c, left.cut(&right));
57 left.has_bits_set()
58 } else {
59 true
60 }
61 });
62 !left.is_empty()
63 } else {
64 true
65 }
66 });
67 !left.is_empty()
68 } else {
69 true
70 }
71 });
72
73 out
74 }
75}
76
77impl<T1: AsRef<[u8]>> Cut<Splinter> for CowSplinter<T1> {
79 type Output = Splinter;
80
81 fn cut(&mut self, rhs: &Splinter) -> Self::Output {
82 self.to_mut().cut(rhs)
83 }
84}
85
86impl<T1: AsRef<[u8]>, T2: AsRef<[u8]>> Cut<SplinterRef<T2>> for CowSplinter<T1> {
88 type Output = Splinter;
89
90 fn cut(&mut self, rhs: &SplinterRef<T2>) -> Self::Output {
91 self.to_mut().cut(rhs)
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use crate::{
98 Splinter,
99 ops::Cut,
100 testutil::{TestSplinter, mksplinter, mksplinters},
101 };
102
103 impl Cut<TestSplinter> for Splinter {
104 type Output = Splinter;
105
106 fn cut(&mut self, rhs: &TestSplinter) -> Self::Output {
107 use TestSplinter::*;
108 match rhs {
109 Splinter(rhs) => self.cut(rhs),
110 SplinterRef(rhs) => self.cut(rhs),
111 }
112 }
113 }
114
115 fn check_cut<L, R, E, O>(left: L, right: R, expected_cut: E, expected_out: O)
116 where
117 L: IntoIterator<Item = u32> + Clone,
118 R: IntoIterator<Item = u32> + Clone,
119 E: IntoIterator<Item = u32> + Clone,
120 O: IntoIterator<Item = u32> + Clone,
121 {
122 let left = mksplinter(left);
123 let right = mksplinters(right);
124 let expected_cut = mksplinter(expected_cut);
125 let expected_out = mksplinter(expected_out);
126 for rhs in right.into_iter() {
127 let mut left = left.clone();
128 let label = format!("lhs: {left:?}, rhs: {rhs:?}");
129 let out = left.cut(&rhs);
130 assert_eq!(left, expected_cut, "cut: {label}");
131 assert_eq!(out, expected_out, "intersection: {label}");
132 }
133 }
134
135 #[test]
136 fn test_sanity() {
137 check_cut(0..0, 0..0, 0..0, 0..0);
138 check_cut(0..10, 0..5, 5..10, 0..5);
139 check_cut(0..10, 0..10, 0..0, 0..10);
140 }
141}