1use std::cmp::Ordering::{self, *};
2
3use crate::{DeepReveal, IsBot, IsTop, LatticeFrom, LatticeOrd, Merge};
4
5#[derive(Copy, Clone, Debug, Default, Eq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct DomPair<Key, Val> {
20 pub key: Key,
24 val: Val,
26}
27
28impl<Key, Val> DomPair<Key, Val> {
29 pub fn new(key: Key, val: Val) -> Self {
31 Self { key, val }
32 }
33
34 pub fn new_from(key: impl Into<Key>, val: impl Into<Val>) -> Self {
36 Self::new(key.into(), val.into())
37 }
38
39 pub fn as_reveal_ref(&self) -> (&Key, &Val) {
41 (&self.key, &self.val)
42 }
43
44 pub fn as_reveal_mut(&mut self) -> (&mut Key, &mut Val) {
46 (&mut self.key, &mut self.val)
47 }
48
49 pub fn into_reveal(self) -> (Key, Val) {
51 (self.key, self.val)
52 }
53}
54
55impl<Key, Val> DeepReveal for DomPair<Key, Val>
56where
57 Key: DeepReveal,
58 Val: DeepReveal,
59{
60 type Revealed = (Key::Revealed, Val::Revealed);
61
62 fn deep_reveal(self) -> Self::Revealed {
63 (self.key.deep_reveal(), self.val.deep_reveal())
64 }
65}
66
67impl<KeySelf, KeyOther, ValSelf, ValOther> Merge<DomPair<KeyOther, ValOther>>
68 for DomPair<KeySelf, ValSelf>
69where
70 KeySelf: Merge<KeyOther> + LatticeFrom<KeyOther> + PartialOrd<KeyOther>,
71 ValSelf: Merge<ValOther> + LatticeFrom<ValOther>,
72{
73 fn merge(&mut self, other: DomPair<KeyOther, ValOther>) -> bool {
74 match self.key.partial_cmp(&other.key) {
75 None => {
76 assert!(self.key.merge(other.key));
77 self.val.merge(other.val);
78 true
79 }
80 Some(Equal) => self.val.merge(other.val),
81 Some(Less) => {
82 *self = LatticeFrom::lattice_from(other);
83 true
84 }
85 Some(Greater) => false,
86 }
87 }
88}
89
90impl<KeySelf, KeyOther, ValSelf, ValOther> LatticeFrom<DomPair<KeyOther, ValOther>>
91 for DomPair<KeySelf, ValSelf>
92where
93 KeySelf: LatticeFrom<KeyOther>,
94 ValSelf: LatticeFrom<ValOther>,
95{
96 fn lattice_from(other: DomPair<KeyOther, ValOther>) -> Self {
97 Self {
98 key: LatticeFrom::lattice_from(other.key),
99 val: LatticeFrom::lattice_from(other.val),
100 }
101 }
102}
103
104impl<KeySelf, KeyOther, ValSelf, ValOther> PartialOrd<DomPair<KeyOther, ValOther>>
105 for DomPair<KeySelf, ValSelf>
106where
107 KeySelf: PartialOrd<KeyOther>,
108 ValSelf: PartialOrd<ValOther>,
109{
110 fn partial_cmp(&self, other: &DomPair<KeyOther, ValOther>) -> Option<Ordering> {
111 match self.key.partial_cmp(&other.key) {
112 Some(Equal) => self.val.partial_cmp(&other.val),
113 otherwise => otherwise,
114 }
115 }
116}
117impl<KeySelf, KeyOther, ValSelf, ValOther> LatticeOrd<DomPair<KeyOther, ValOther>>
118 for DomPair<KeySelf, ValSelf>
119where
120 Self: PartialOrd<DomPair<KeyOther, ValOther>>,
121{
122}
123
124impl<KeySelf, KeyOther, ValSelf, ValOther> PartialEq<DomPair<KeyOther, ValOther>>
125 for DomPair<KeySelf, ValSelf>
126where
127 KeySelf: PartialEq<KeyOther>,
128 ValSelf: PartialEq<ValOther>,
129{
130 fn eq(&self, other: &DomPair<KeyOther, ValOther>) -> bool {
131 if self.key != other.key {
132 return false;
133 }
134
135 if self.val != other.val {
136 return false;
137 }
138
139 true
140 }
141}
142
143impl<Key, Val> IsBot for DomPair<Key, Val>
144where
145 Key: IsBot,
146 Val: IsBot,
147{
148 fn is_bot(&self) -> bool {
149 self.key.is_bot() && self.val.is_bot()
150 }
151}
152
153impl<Key, Val> IsTop for DomPair<Key, Val>
154where
155 Key: IsTop,
156 Val: IsTop,
157{
158 fn is_top(&self) -> bool {
159 self.key.is_top() && self.val.is_top()
160 }
161}
162
163#[cfg(test)]
164mod test {
165 use std::collections::HashSet;
166
167 use super::*;
168 use crate::WithTop;
169 use crate::ord::Max;
170 use crate::set_union::SetUnionHashSet;
171 use crate::test::{
172 check_lattice_is_bot, check_lattice_is_top, check_lattice_ord, check_lattice_properties,
173 check_partial_ord_properties,
174 };
175
176 #[test]
177 fn consistency() {
178 let mut test_vec = Vec::new();
179
180 for a in [vec![], vec![0], vec![1], vec![0, 1]] {
181 for b in [vec![], vec![0], vec![1], vec![0, 1]] {
182 test_vec.push(DomPair::new(
183 SetUnionHashSet::new_from(HashSet::from_iter(a.clone())),
184 SetUnionHashSet::new_from(HashSet::from_iter(b.clone())),
185 ));
186 }
187 }
188
189 check_lattice_ord(&test_vec);
190 check_partial_ord_properties(&test_vec);
191 check_lattice_is_bot(&test_vec);
192 assert!(std::panic::catch_unwind(|| check_lattice_properties(&test_vec)).is_err());
194 }
195
196 #[test]
197 fn consistency_withtop() {
198 let mut test_vec = vec![];
199
200 let sub_items = &[
201 Some(&[] as &[usize]),
202 Some(&[0]),
203 Some(&[1]),
204 Some(&[0, 1]),
205 None,
206 ];
207
208 for a in sub_items {
209 for b in sub_items {
210 test_vec.push(DomPair::new(
211 WithTop::new(
212 a.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
213 ),
214 WithTop::new(
215 b.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
216 ),
217 ));
218 }
219 }
220
221 check_lattice_ord(&test_vec);
222 check_partial_ord_properties(&test_vec);
223 check_lattice_is_bot(&test_vec);
224 check_lattice_is_top(&test_vec);
225 assert!(std::panic::catch_unwind(|| check_lattice_properties(&test_vec)).is_err());
227 }
228
229 #[test]
230 fn consistency_with_ord_lhs() {
231 let mut test_vec = Vec::new();
232
233 for a in [0, 1, 2] {
234 for b in [vec![], vec![0], vec![1], vec![0, 1]] {
235 test_vec.push(DomPair::new(
236 Max::new(a),
237 SetUnionHashSet::new_from(HashSet::from_iter(b.clone())),
238 ));
239 }
240 }
241
242 check_lattice_ord(&test_vec);
243 check_lattice_properties(&test_vec);
244 check_partial_ord_properties(&test_vec);
245 }
246}