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 #[test]
78 fn consistency() {
79 let mut test_vec = Vec::new();
80
81 for a in [vec![], vec![0], vec![1], vec![0, 1]] {
82 for b in [vec![], vec![0], vec![1], vec![0, 1]] {
83 test_vec.push(Pair::new(
84 SetUnionHashSet::new_from(HashSet::from_iter(a.clone())),
85 SetUnionHashSet::new_from(HashSet::from_iter(b.clone())),
86 ));
87 }
88 }
89
90 check_all(&test_vec);
91 }
92
93 #[test]
94 fn consistency_withtop() {
95 let mut test_vec = vec![];
96
97 let sub_items = &[
98 Some(&[] as &[usize]),
99 Some(&[0]),
100 Some(&[1]),
101 Some(&[0, 1]),
102 None,
103 ];
104
105 for a in sub_items {
106 for b in sub_items {
107 test_vec.push(Pair::new(
108 WithTop::new(
109 a.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
110 ),
111 WithTop::new(
112 b.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
113 ),
114 ));
115 }
116 }
117
118 check_all(&test_vec);
119 }
120
121 #[test]
122 fn test_merge_direction() {
123 let src = Pair::new(
124 SetUnionSingletonSet::new_from(5),
125 SetUnionSingletonSet::new_from("hello"),
126 );
127 let mut dst = Pair::new(
128 SetUnionHashSet::new_from([1, 2]),
129 SetUnionBTreeSet::new_from(["world"]),
130 );
131 dst.merge(src);
132 }
133
134 #[test]
135 fn test_pair_bimorphism() {
136 let items_a = &[
137 SetUnionHashSet::new_from([]),
138 SetUnionHashSet::new_from([0]),
139 SetUnionHashSet::new_from([1]),
140 SetUnionHashSet::new_from([0, 1]),
141 ];
142 let items_b = &[
143 SetUnionBTreeSet::new("hello".chars().collect()),
144 SetUnionBTreeSet::new("world".chars().collect()),
145 ];
146
147 check_lattice_bimorphism(PairBimorphism, items_a, items_a);
148 check_lattice_bimorphism(PairBimorphism, items_a, items_b);
149 check_lattice_bimorphism(PairBimorphism, items_b, items_a);
150 check_lattice_bimorphism(PairBimorphism, items_b, items_b);
151 }
152}