1use crate::{DeepReveal, Lattice, LatticeBimorphism};
2
3#[derive(Copy, Clone, Debug, Default, Eq, Lattice)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Pair<LatA, LatB> {
11 pub a: LatA,
13
14 pub b: LatB,
16}
17
18impl<LatA, LatB> Pair<LatA, LatB> {
19 pub fn new(a: LatA, b: LatB) -> Self {
21 Self { a, b }
22 }
23
24 pub fn new_from(a: impl Into<LatA>, b: impl Into<LatB>) -> Self {
26 Self::new(a.into(), b.into())
27 }
28
29 pub fn as_reveal_ref(&self) -> (&LatA, &LatB) {
31 (&self.a, &self.b)
32 }
33
34 pub fn as_reveal_mut(&mut self) -> (&mut LatA, &mut LatB) {
36 (&mut self.a, &mut self.b)
37 }
38
39 pub fn into_reveal(self) -> (LatA, LatB) {
41 (self.a, self.b)
42 }
43}
44
45impl<LatA, LatB> DeepReveal for Pair<LatA, LatB>
46where
47 LatA: DeepReveal,
48 LatB: DeepReveal,
49{
50 type Revealed = (LatA::Revealed, LatB::Revealed);
51
52 fn deep_reveal(self) -> Self::Revealed {
53 (self.a.deep_reveal(), self.b.deep_reveal())
54 }
55}
56
57#[derive(Default)]
59pub struct PairBimorphism;
60impl<LatA, LatB> LatticeBimorphism<LatA, LatB> for PairBimorphism {
61 type Output = Pair<LatA, LatB>;
62
63 fn call(&mut self, lat_a: LatA, lat_b: LatB) -> Self::Output {
64 Pair::new(lat_a, lat_b)
65 }
66}
67
68#[cfg(test)]
69mod test {
70 use std::collections::HashSet;
71
72 use super::*;
73 use crate::set_union::{SetUnionBTreeSet, SetUnionHashSet, SetUnionSingletonSet};
74 use crate::test::{check_all, check_lattice_bimorphism};
75 use crate::{Merge, WithTop};
76
77 #[cfg(feature = "alloc")]
78 #[test]
79 fn consistency() {
80 use alloc::vec;
81
82 let mut test_vec = vec![];
83
84 for a in [vec![], vec![0], vec![1], vec![0, 1]] {
85 for b in [vec![], vec![0], vec![1], vec![0, 1]] {
86 test_vec.push(Pair::new(
87 SetUnionHashSet::new_from(HashSet::from_iter(a.clone())),
88 SetUnionHashSet::new_from(HashSet::from_iter(b.clone())),
89 ));
90 }
91 }
92
93 check_all(&test_vec);
94 }
95
96 #[cfg(feature = "alloc")]
97 #[test]
98 fn consistency_withtop() {
99 use alloc::vec::Vec;
100
101 let mut test_vec = Vec::new();
102
103 let sub_items = &[
104 Some(&[] as &[usize]),
105 Some(&[0]),
106 Some(&[1]),
107 Some(&[0, 1]),
108 None,
109 ];
110
111 for a in sub_items {
112 for b in sub_items {
113 test_vec.push(Pair::new(
114 WithTop::new(
115 a.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
116 ),
117 WithTop::new(
118 b.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
119 ),
120 ));
121 }
122 }
123
124 check_all(&test_vec);
125 }
126
127 #[test]
128 fn test_merge_direction() {
129 let src = Pair::new(
130 SetUnionSingletonSet::new_from(5),
131 SetUnionSingletonSet::new_from("hello"),
132 );
133 let mut dst = Pair::new(
134 SetUnionHashSet::new_from([1, 2]),
135 SetUnionBTreeSet::new_from(["world"]),
136 );
137 dst.merge(src);
138 }
139
140 #[test]
141 fn test_pair_bimorphism() {
142 let items_a = &[
143 SetUnionHashSet::new_from([]),
144 SetUnionHashSet::new_from([0]),
145 SetUnionHashSet::new_from([1]),
146 SetUnionHashSet::new_from([0, 1]),
147 ];
148 let items_b = &[
149 SetUnionBTreeSet::new("hello".chars().collect()),
150 SetUnionBTreeSet::new("world".chars().collect()),
151 ];
152
153 check_lattice_bimorphism(PairBimorphism, items_a, items_a);
154 check_lattice_bimorphism(PairBimorphism, items_a, items_b);
155 check_lattice_bimorphism(PairBimorphism, items_b, items_a);
156 check_lattice_bimorphism(PairBimorphism, items_b, items_b);
157 }
158}