1#[cfg(feature = "alloc")]
4use alloc::collections::BTreeMap;
5use core::cmp::Ordering::{self, *};
6use core::fmt::Debug;
7use core::marker::PhantomData;
8#[cfg(feature = "std")]
9use std::collections::HashMap;
10
11use cc_traits::{Collection, GetKeyValue, Iter, MapInsert, SimpleCollectionRef};
12
13#[cfg(feature = "alloc")]
14use crate::cc_traits::GetMut;
15use crate::cc_traits::{Keyed, Map, MapIter, SimpleKeyedRef};
16#[cfg(feature = "alloc")]
17use crate::collections::VecMap;
18use crate::collections::{ArrayMap, MapMapValues, OptionMap, SingletonMap};
19#[cfg(feature = "alloc")]
20use crate::{Atomize, Merge};
21use crate::{DeepReveal, IsBot, IsTop, LatticeBimorphism, LatticeFrom, LatticeOrd};
22
23#[repr(transparent)]
28#[derive(Copy, Clone, Debug, Default)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct MapUnion<Map>(Map);
31impl<Map> MapUnion<Map> {
32 pub fn new(val: Map) -> Self {
34 Self(val)
35 }
36
37 pub fn new_from(val: impl Into<Map>) -> Self {
39 Self::new(val.into())
40 }
41
42 pub fn as_reveal_ref(&self) -> &Map {
44 &self.0
45 }
46
47 pub fn as_reveal_mut(&mut self) -> &mut Map {
49 &mut self.0
50 }
51
52 pub fn into_reveal(self) -> Map {
54 self.0
55 }
56}
57
58impl<Map, Val> DeepReveal for MapUnion<Map>
59where
60 Map: Keyed<Item = Val> + MapMapValues<Val>,
61 Val: DeepReveal,
62{
63 type Revealed = Map::MapValue<Val::Revealed>;
64
65 fn deep_reveal(self) -> Self::Revealed {
66 self.0.map_values(DeepReveal::deep_reveal)
67 }
68}
69
70#[cfg(feature = "alloc")]
71impl<MapSelf, MapOther, K, ValSelf, ValOther> Merge<MapUnion<MapOther>> for MapUnion<MapSelf>
72where
73 MapSelf: Keyed<Key = K, Item = ValSelf>
74 + Extend<(K, ValSelf)>
75 + for<'a> GetMut<&'a K, Item = ValSelf>,
76 MapOther: IntoIterator<Item = (K, ValOther)>,
77 ValSelf: Merge<ValOther> + LatticeFrom<ValOther>,
78 ValOther: IsBot,
79{
80 fn merge(&mut self, other: MapUnion<MapOther>) -> bool {
81 use alloc::vec::Vec;
82
83 let mut changed = false;
84 let iter: Vec<_> = other
89 .0
90 .into_iter()
91 .filter(|(_k_other, val_other)| !val_other.is_bot())
92 .filter_map(|(k_other, val_other)| {
93 if let Some(mut val_self) = self.0.get_mut(&k_other) {
94 changed |= val_self.merge(val_other);
96 None
97 } else {
98 changed = true;
100 Some((k_other, ValSelf::lattice_from(val_other)))
101 }
102 })
103 .collect();
104 self.0.extend(iter);
105 changed
106 }
107}
108
109impl<MapSelf, MapOther, K, ValSelf, ValOther> LatticeFrom<MapUnion<MapOther>> for MapUnion<MapSelf>
110where
111 MapSelf: Keyed<Key = K, Item = ValSelf> + FromIterator<(K, ValSelf)>,
112 MapOther: IntoIterator<Item = (K, ValOther)>,
113 ValSelf: LatticeFrom<ValOther>,
114{
115 fn lattice_from(other: MapUnion<MapOther>) -> Self {
116 Self(
117 other
118 .0
119 .into_iter()
120 .map(|(k_other, val_other)| (k_other, LatticeFrom::lattice_from(val_other)))
121 .collect(),
122 )
123 }
124}
125
126impl<MapSelf, MapOther, K, ValSelf, ValOther> PartialOrd<MapUnion<MapOther>> for MapUnion<MapSelf>
127where
128 MapSelf: Map<K, ValSelf, Key = K, Item = ValSelf> + MapIter + SimpleKeyedRef,
129 MapOther: Map<K, ValOther, Key = K, Item = ValOther> + MapIter + SimpleKeyedRef,
130 ValSelf: PartialOrd<ValOther> + IsBot,
131 ValOther: IsBot,
132{
133 fn partial_cmp(&self, other: &MapUnion<MapOther>) -> Option<Ordering> {
134 let mut self_any_greater = false;
135 let mut other_any_greater = false;
136 let self_keys = self
137 .0
138 .iter()
139 .filter(|(_k, v)| !v.is_bot())
140 .map(|(k, _v)| <MapSelf as SimpleKeyedRef>::into_ref(k));
141 let other_keys = other
142 .0
143 .iter()
144 .filter(|(_k, v)| !v.is_bot())
145 .map(|(k, _v)| <MapOther as SimpleKeyedRef>::into_ref(k));
146 for k in self_keys.chain(other_keys) {
147 match (self.0.get(k), other.0.get(k)) {
148 (Some(self_value), Some(other_value)) => {
149 match self_value.partial_cmp(&*other_value)? {
150 Less => {
151 other_any_greater = true;
152 }
153 Greater => {
154 self_any_greater = true;
155 }
156 Equal => {}
157 }
158 }
159 (Some(_), None) => {
160 self_any_greater = true;
161 }
162 (None, Some(_)) => {
163 other_any_greater = true;
164 }
165 (None, None) => unreachable!(),
166 }
167 if self_any_greater && other_any_greater {
168 return None;
169 }
170 }
171 match (self_any_greater, other_any_greater) {
172 (true, false) => Some(Greater),
173 (false, true) => Some(Less),
174 (false, false) => Some(Equal),
175 (true, true) => unreachable!(),
177 }
178 }
179}
180impl<MapSelf, MapOther> LatticeOrd<MapUnion<MapOther>> for MapUnion<MapSelf> where
181 Self: PartialOrd<MapUnion<MapOther>>
182{
183}
184
185impl<MapSelf, MapOther, K, ValSelf, ValOther> PartialEq<MapUnion<MapOther>> for MapUnion<MapSelf>
186where
187 MapSelf: Map<K, ValSelf, Key = K, Item = ValSelf> + MapIter + SimpleKeyedRef,
188 MapOther: Map<K, ValOther, Key = K, Item = ValOther> + MapIter + SimpleKeyedRef,
189 ValSelf: PartialEq<ValOther> + IsBot,
190 ValOther: IsBot,
191{
192 fn eq(&self, other: &MapUnion<MapOther>) -> bool {
193 let self_keys = self
194 .0
195 .iter()
196 .filter(|(_k, v)| !v.is_bot())
197 .map(|(k, _v)| <MapSelf as SimpleKeyedRef>::into_ref(k));
198 let other_keys = other
199 .0
200 .iter()
201 .filter(|(_k, v)| !v.is_bot())
202 .map(|(k, _v)| <MapOther as SimpleKeyedRef>::into_ref(k));
203 for k in self_keys.chain(other_keys) {
204 match (self.0.get(k), other.0.get(k)) {
205 (Some(self_value), Some(other_value)) => {
206 if *self_value != *other_value {
207 return false;
208 }
209 }
210 (None, None) => unreachable!(),
211 _ => {
212 return false;
213 }
214 }
215 }
216
217 true
218 }
219}
220impl<MapSelf> Eq for MapUnion<MapSelf> where Self: PartialEq {}
221
222impl<Map> IsBot for MapUnion<Map>
223where
224 Map: Iter,
225 Map::Item: IsBot,
226{
227 fn is_bot(&self) -> bool {
228 self.0.iter().all(|v| v.is_bot())
229 }
230}
231
232impl<Map> IsTop for MapUnion<Map> {
233 fn is_top(&self) -> bool {
234 false
235 }
236}
237
238#[cfg(feature = "alloc")]
239impl<Map, K, Val> Atomize for MapUnion<Map>
240where
241 Map: 'static
242 + IntoIterator<Item = (K, Val)>
243 + Keyed<Key = K, Item = Val>
244 + Extend<(K, Val)>
245 + for<'a> GetMut<&'a K, Item = Val>,
246 K: 'static + Clone,
247 Val: 'static + Atomize + LatticeFrom<<Val as Atomize>::Atom>,
248{
249 type Atom = MapUnionSingletonMap<K, Val::Atom>;
250
251 type AtomIter = alloc::boxed::Box<dyn Iterator<Item = Self::Atom>>;
253
254 fn atomize(self) -> Self::AtomIter {
255 alloc::boxed::Box::new(self.0.into_iter().flat_map(|(k, val)| {
256 val.atomize()
257 .map(move |v| MapUnionSingletonMap::new_from((k.clone(), v)))
258 }))
259 }
260}
261
262#[cfg(feature = "std")]
264pub type MapUnionHashMap<K, Val> = MapUnion<HashMap<K, Val>>;
265
266#[cfg(feature = "alloc")]
268pub type MapUnionBTreeMap<K, Val> = MapUnion<BTreeMap<K, Val>>;
269
270#[cfg(feature = "alloc")]
272pub type MapUnionVec<K, Val> = MapUnion<VecMap<K, Val>>;
273
274pub type MapUnionArrayMap<K, Val, const N: usize> = MapUnion<ArrayMap<K, Val, N>>;
276
277pub type MapUnionSingletonMap<K, Val> = MapUnion<SingletonMap<K, Val>>;
279
280pub type MapUnionOptionMap<K, Val> = MapUnion<OptionMap<K, Val>>;
282
283pub struct KeyedBimorphism<MapOut, Bimorphism> {
287 bimorphism: Bimorphism,
288 _phantom: PhantomData<fn() -> MapOut>,
289}
290impl<MapOut, Bimorphism> KeyedBimorphism<MapOut, Bimorphism> {
291 pub fn new(bimorphism: Bimorphism) -> Self {
293 Self {
294 bimorphism,
295 _phantom: PhantomData,
296 }
297 }
298}
299impl<MapA, MapB, MapOut, ValFunc> LatticeBimorphism<MapUnion<MapA>, MapUnion<MapB>>
300 for KeyedBimorphism<MapOut, ValFunc>
301where
302 ValFunc: LatticeBimorphism<MapA::Item, MapB::Item>,
303 MapA: MapIter + SimpleKeyedRef + SimpleCollectionRef,
304 MapB: for<'a> GetKeyValue<&'a MapA::Key, Key = MapA::Key> + SimpleCollectionRef,
305 MapA::Key: Clone + Eq,
306 MapA::Item: Clone,
307 MapB::Item: Clone,
308 MapOut: Default + MapInsert<MapA::Key> + Collection<Item = ValFunc::Output>,
309{
310 type Output = MapUnion<MapOut>;
311
312 fn call(&mut self, lat_a: MapUnion<MapA>, lat_b: MapUnion<MapB>) -> Self::Output {
313 let mut output = MapUnion::<MapOut>::default();
314 for (key, val_a) in lat_a.as_reveal_ref().iter() {
315 let key = <MapA as SimpleKeyedRef>::into_ref(key);
316 let Some((_key, val_b)) = lat_b.as_reveal_ref().get_key_value(key) else {
317 continue;
318 };
319 let val_a = <MapA as SimpleCollectionRef>::into_ref(val_a).clone();
320 let val_b = <MapB as SimpleCollectionRef>::into_ref(val_b).clone();
321
322 let val_out = LatticeBimorphism::call(&mut self.bimorphism, val_a, val_b);
323 <MapOut as MapInsert<_>>::insert(output.as_reveal_mut(), key.clone(), val_out);
324 }
325 output
326 }
327}
328
329#[cfg(test)]
330mod test {
331 use std::collections::HashSet;
332
333 use super::*;
334 use crate::collections::SingletonSet;
335 use crate::set_union::{CartesianProductBimorphism, SetUnionHashSet, SetUnionSingletonSet};
336 use crate::test::{cartesian_power, check_all, check_atomize_each, check_lattice_bimorphism};
337
338 #[test]
339 fn test_map_union() {
340 let mut my_map_a = <MapUnionHashMap<&str, SetUnionHashSet<u64>>>::default();
341 let my_map_b = <MapUnionSingletonMap<&str, SetUnionSingletonSet<u64>>>::new(SingletonMap(
342 "hello",
343 SetUnionSingletonSet::new(SingletonSet(100)),
344 ));
345 let my_map_c =
346 MapUnionSingletonMap::new_from(("hello", SetUnionHashSet::new_from([100, 200])));
347 my_map_a.merge(my_map_b);
348 my_map_a.merge(my_map_c);
349 }
350
351 #[cfg(feature = "alloc")]
352 #[test]
353 fn consistency_atomize() {
354 use alloc::vec;
355 use alloc::vec::Vec;
356
357 let mut test_vec = Vec::new();
358
359 test_vec.push(MapUnionHashMap::default());
361 for key in [0, 1] {
363 for value in [vec![], vec![0], vec![1], vec![0, 1]] {
364 test_vec.push(MapUnionHashMap::new(HashMap::from_iter([(
365 key,
366 SetUnionHashSet::new(HashSet::from_iter(value)),
367 )])));
368 }
369 }
370 for [val_a, val_b] in cartesian_power(&[vec![], vec![0], vec![1], vec![0, 1]]) {
372 test_vec.push(MapUnionHashMap::new(HashMap::from_iter([
373 (0, SetUnionHashSet::new(HashSet::from_iter(val_a.clone()))),
374 (1, SetUnionHashSet::new(HashSet::from_iter(val_b.clone()))),
375 ])));
376 }
377
378 check_all(&test_vec);
379 check_atomize_each(&test_vec);
380 }
381
382 #[test]
384 fn test_collapes_bot() {
385 let map_empty = <MapUnionHashMap<&str, SetUnionHashSet<u64>>>::default();
386 let map_a_bot = <MapUnionSingletonMap<&str, SetUnionHashSet<u64>>>::new(SingletonMap(
387 "a",
388 Default::default(),
389 ));
390 let map_b_bot = <MapUnionSingletonMap<&str, SetUnionHashSet<u64>>>::new(SingletonMap(
391 "b",
392 Default::default(),
393 ));
394
395 assert_eq!(map_empty, map_a_bot);
396 assert_eq!(map_empty, map_b_bot);
397 assert_eq!(map_a_bot, map_b_bot);
398 }
399
400 #[test]
401 fn test_join_aka_keyed_cartesian_product() {
402 let items_a = &[
403 MapUnionHashMap::new_from([("foo", SetUnionHashSet::new_from(["bar"]))]),
404 MapUnionHashMap::new_from([("foo", SetUnionHashSet::new_from(["baz"]))]),
405 MapUnionHashMap::new_from([("hello", SetUnionHashSet::new_from(["world"]))]),
406 ];
407 let items_b = &[
408 MapUnionHashMap::new_from([("foo", SetUnionHashSet::new_from(["bang"]))]),
409 MapUnionHashMap::new_from([(
410 "hello",
411 SetUnionHashSet::new_from(["goodbye", "farewell"]),
412 )]),
413 ];
414
415 check_lattice_bimorphism(
416 KeyedBimorphism::<HashMap<_, _>, _>::new(
417 CartesianProductBimorphism::<HashSet<_>>::default(),
418 ),
419 items_a,
420 items_a,
421 );
422 check_lattice_bimorphism(
423 KeyedBimorphism::<HashMap<_, _>, _>::new(
424 CartesianProductBimorphism::<HashSet<_>>::default(),
425 ),
426 items_a,
427 items_b,
428 );
429 check_lattice_bimorphism(
430 KeyedBimorphism::<HashMap<_, _>, _>::new(
431 CartesianProductBimorphism::<HashSet<_>>::default(),
432 ),
433 items_b,
434 items_a,
435 );
436 check_lattice_bimorphism(
437 KeyedBimorphism::<HashMap<_, _>, _>::new(
438 CartesianProductBimorphism::<HashSet<_>>::default(),
439 ),
440 items_b,
441 items_b,
442 );
443
444 check_lattice_bimorphism(
445 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
446 CartesianProductBimorphism::<HashSet<_>>::default(),
447 ),
448 items_a,
449 items_a,
450 );
451 check_lattice_bimorphism(
452 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
453 CartesianProductBimorphism::<HashSet<_>>::default(),
454 ),
455 items_a,
456 items_b,
457 );
458 check_lattice_bimorphism(
459 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
460 CartesianProductBimorphism::<HashSet<_>>::default(),
461 ),
462 items_b,
463 items_a,
464 );
465 check_lattice_bimorphism(
466 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
467 CartesianProductBimorphism::<HashSet<_>>::default(),
468 ),
469 items_b,
470 items_b,
471 );
472 }
473}