lattices/
pair.rs

1use crate::{DeepReveal, Lattice, LatticeBimorphism};
2
3/// Pair compound lattice.
4///
5/// `LatA` and `LatB` specify the nested lattice types.
6///
7/// When merging, both sub-lattices are always merged.
8#[derive(Copy, Clone, Debug, Default, Eq, Lattice)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Pair<LatA, LatB> {
11    /// The "left" Lattice of the Pair lattice.
12    pub a: LatA,
13
14    /// The "right" Lattice of the Pair lattice.
15    pub b: LatB,
16}
17
18impl<LatA, LatB> Pair<LatA, LatB> {
19    /// Create a `Pair` from the given values.
20    pub fn new(a: LatA, b: LatB) -> Self {
21        Self { a, b }
22    }
23
24    /// Create a `Pair` from the given values, using `Into`.
25    pub fn new_from(a: impl Into<LatA>, b: impl Into<LatB>) -> Self {
26        Self::new(a.into(), b.into())
27    }
28
29    /// Reveal the inner value as a shared reference.
30    pub fn as_reveal_ref(&self) -> (&LatA, &LatB) {
31        (&self.a, &self.b)
32    }
33
34    /// Reveal the inner value as an exclusive reference.
35    pub fn as_reveal_mut(&mut self) -> (&mut LatA, &mut LatB) {
36        (&mut self.a, &mut self.b)
37    }
38
39    /// Gets the inner by value, consuming self.
40    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/// Bimorphism which pairs up the two input lattices.
58#[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}