#![expect(missing_docs)] // https://github.com/rust-lang/rust/issues/137561 #![cfg(feature = "rayon")] use hashbrown::{HashMap, HashSet}; use rayon::iter::{ IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelExtend, ParallelIterator, }; use std::sync::LazyLock; macro_rules! assert_eq3 { ($e1:expr, $e2:expr, $e3:expr) => {{ assert_eq!($e1, $e2); assert_eq!($e1, $e3); assert_eq!($e2, $e3); }}; } static MAP_EMPTY: LazyLock> = LazyLock::new(HashMap::new); static MAP: LazyLock> = LazyLock::new(|| { let mut m = HashMap::new(); m.insert('b', 20); m.insert('a', 10); m.insert('c', 30); m.insert('e', 50); m.insert('f', 60); m.insert('d', 40); m }); #[test] fn map_seq_par_equivalence_iter_empty() { let vec_seq = MAP_EMPTY.iter().collect::>(); let vec_par = MAP_EMPTY.par_iter().collect::>(); assert_eq3!(vec_seq, vec_par, []); } #[test] fn map_seq_par_equivalence_iter() { let mut vec_seq = MAP.iter().collect::>(); let mut vec_par = MAP.par_iter().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [ (&'a', &10), (&'b', &20), (&'c', &30), (&'d', &40), (&'e', &50), (&'f', &60), ]; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } #[test] fn map_seq_par_equivalence_keys_empty() { let vec_seq = MAP_EMPTY.keys().collect::>(); let vec_par = MAP_EMPTY.par_keys().collect::>(); let expected: [&char; 0] = []; assert_eq3!(vec_seq, vec_par, expected); } #[test] fn map_seq_par_equivalence_keys() { let mut vec_seq = MAP.keys().collect::>(); let mut vec_par = MAP.par_keys().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f']; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } #[test] fn map_seq_par_equivalence_values_empty() { let vec_seq = MAP_EMPTY.values().collect::>(); let vec_par = MAP_EMPTY.par_values().collect::>(); let expected: [&u32; 0] = []; assert_eq3!(vec_seq, vec_par, expected); } #[test] fn map_seq_par_equivalence_values() { let mut vec_seq = MAP.values().collect::>(); let mut vec_par = MAP.par_values().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [&10, &20, &30, &40, &50, &60]; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } #[test] fn map_seq_par_equivalence_iter_mut_empty() { let mut map1 = MAP_EMPTY.clone(); let mut map2 = MAP_EMPTY.clone(); let vec_seq = map1.iter_mut().collect::>(); let vec_par = map2.par_iter_mut().collect::>(); assert_eq3!(vec_seq, vec_par, []); } #[test] fn map_seq_par_equivalence_iter_mut() { let mut map1 = MAP.clone(); let mut map2 = MAP.clone(); let mut vec_seq = map1.iter_mut().collect::>(); let mut vec_par = map2.par_iter_mut().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [ (&'a', &mut 10), (&'b', &mut 20), (&'c', &mut 30), (&'d', &mut 40), (&'e', &mut 50), (&'f', &mut 60), ]; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } #[test] fn map_seq_par_equivalence_values_mut_empty() { let mut map1 = MAP_EMPTY.clone(); let mut map2 = MAP_EMPTY.clone(); let vec_seq = map1.values_mut().collect::>(); let vec_par = map2.par_values_mut().collect::>(); let expected: [&u32; 0] = []; assert_eq3!(vec_seq, vec_par, expected); } #[test] fn map_seq_par_equivalence_values_mut() { let mut map1 = MAP.clone(); let mut map2 = MAP.clone(); let mut vec_seq = map1.values_mut().collect::>(); let mut vec_par = map2.par_values_mut().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [&mut 10, &mut 20, &mut 30, &mut 40, &mut 50, &mut 60]; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } #[test] fn map_seq_par_equivalence_into_iter_empty() { let vec_seq = MAP_EMPTY.clone().into_iter().collect::>(); let vec_par = MAP_EMPTY.clone().into_par_iter().collect::>(); assert_eq3!(vec_seq, vec_par, []); } #[test] fn map_seq_par_equivalence_into_iter() { let mut vec_seq = MAP.clone().into_iter().collect::>(); let mut vec_par = MAP.clone().into_par_iter().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [ ('a', 10), ('b', 20), ('c', 30), ('d', 40), ('e', 50), ('f', 60), ]; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } static MAP_VEC_EMPTY: &[(char, u32)] = &[]; static MAP_VEC: &[(char, u32)] = &[ ('b', 20), ('a', 10), ('c', 30), ('e', 50), ('f', 60), ('d', 40), ]; #[test] fn map_seq_par_equivalence_collect_empty() { let map_expected = MAP_EMPTY.clone(); let map_seq = MAP_VEC_EMPTY.iter().copied().collect::>(); let map_par = MAP_VEC_EMPTY.par_iter().copied().collect::>(); assert_eq!(map_seq, map_par); assert_eq!(map_seq, map_expected); assert_eq!(map_par, map_expected); } #[test] fn map_seq_par_equivalence_collect() { let map_expected = MAP.clone(); let map_seq = MAP_VEC.iter().copied().collect::>(); let map_par = MAP_VEC.par_iter().copied().collect::>(); assert_eq!(map_seq, map_par); assert_eq!(map_seq, map_expected); assert_eq!(map_par, map_expected); } static MAP_EXISTING_EMPTY: LazyLock> = LazyLock::new(HashMap::new); static MAP_EXISTING: LazyLock> = LazyLock::new(|| { let mut m = HashMap::new(); m.insert('b', 20); m.insert('a', 10); m }); static MAP_EXTENSION_EMPTY: &[(char, u32)] = &[]; static MAP_EXTENSION: &[(char, u32)] = &[('c', 30), ('e', 50), ('f', 60), ('d', 40)]; #[test] fn map_seq_par_equivalence_existing_empty_extend_empty() { let expected = HashMap::new(); let mut map_seq = MAP_EXISTING_EMPTY.clone(); let mut map_par = MAP_EXISTING_EMPTY.clone(); map_seq.extend(MAP_EXTENSION_EMPTY.iter().copied()); map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } #[test] fn map_seq_par_equivalence_existing_empty_extend() { let expected = MAP_EXTENSION.iter().copied().collect::>(); let mut map_seq = MAP_EXISTING_EMPTY.clone(); let mut map_par = MAP_EXISTING_EMPTY.clone(); map_seq.extend(MAP_EXTENSION.iter().copied()); map_par.par_extend(MAP_EXTENSION.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } #[test] fn map_seq_par_equivalence_existing_extend_empty() { let expected = MAP_EXISTING.clone(); let mut map_seq = MAP_EXISTING.clone(); let mut map_par = MAP_EXISTING.clone(); map_seq.extend(MAP_EXTENSION_EMPTY.iter().copied()); map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } #[test] fn map_seq_par_equivalence_existing_extend() { let expected = MAP.clone(); let mut map_seq = MAP_EXISTING.clone(); let mut map_par = MAP_EXISTING.clone(); map_seq.extend(MAP_EXTENSION.iter().copied()); map_par.par_extend(MAP_EXTENSION.par_iter().copied()); assert_eq3!(map_seq, map_par, expected); } static SET_EMPTY: LazyLock> = LazyLock::new(HashSet::new); static SET: LazyLock> = LazyLock::new(|| { let mut s = HashSet::new(); s.insert('b'); s.insert('a'); s.insert('c'); s.insert('e'); s.insert('f'); s.insert('d'); s }); #[test] fn set_seq_par_equivalence_iter_empty() { let vec_seq = SET_EMPTY.iter().collect::>(); let vec_par = SET_EMPTY.par_iter().collect::>(); let expected: [&char; 0] = []; assert_eq3!(vec_seq, vec_par, expected); } #[test] fn set_seq_par_equivalence_iter() { let mut vec_seq = SET.iter().collect::>(); let mut vec_par = SET.par_iter().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f']; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } #[test] fn set_seq_par_equivalence_into_iter_empty() { let vec_seq = SET_EMPTY.clone().into_iter().collect::>(); let vec_par = SET_EMPTY.clone().into_par_iter().collect::>(); // Work around type inference failure introduced by rend dev-dependency. let empty: [char; 0] = []; assert_eq3!(vec_seq, vec_par, empty); } #[test] fn set_seq_par_equivalence_into_iter() { let mut vec_seq = SET.clone().into_iter().collect::>(); let mut vec_par = SET.clone().into_par_iter().collect::>(); assert_eq!(vec_seq, vec_par); // Do not depend on the exact order of values let expected_sorted = ['a', 'b', 'c', 'd', 'e', 'f']; vec_seq.sort_unstable(); vec_par.sort_unstable(); assert_eq3!(vec_seq, vec_par, expected_sorted); } static SET_VEC_EMPTY: &[char] = &[]; static SET_VEC: &[char] = &['b', 'a', 'c', 'e', 'f', 'd']; #[test] fn set_seq_par_equivalence_collect_empty() { let set_expected = SET_EMPTY.clone(); let set_seq = SET_VEC_EMPTY.iter().copied().collect::>(); let set_par = SET_VEC_EMPTY.par_iter().copied().collect::>(); assert_eq!(set_seq, set_par); assert_eq!(set_seq, set_expected); assert_eq!(set_par, set_expected); } #[test] fn set_seq_par_equivalence_collect() { let set_expected = SET.clone(); let set_seq = SET_VEC.iter().copied().collect::>(); let set_par = SET_VEC.par_iter().copied().collect::>(); assert_eq!(set_seq, set_par); assert_eq!(set_seq, set_expected); assert_eq!(set_par, set_expected); } static SET_EXISTING_EMPTY: LazyLock> = LazyLock::new(HashSet::new); static SET_EXISTING: LazyLock> = LazyLock::new(|| { let mut s = HashSet::new(); s.insert('b'); s.insert('a'); s }); static SET_EXTENSION_EMPTY: &[char] = &[]; static SET_EXTENSION: &[char] = &['c', 'e', 'f', 'd']; #[test] fn set_seq_par_equivalence_existing_empty_extend_empty() { let expected = HashSet::new(); let mut set_seq = SET_EXISTING_EMPTY.clone(); let mut set_par = SET_EXISTING_EMPTY.clone(); set_seq.extend(SET_EXTENSION_EMPTY.iter().copied()); set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } #[test] fn set_seq_par_equivalence_existing_empty_extend() { let expected = SET_EXTENSION.iter().copied().collect::>(); let mut set_seq = SET_EXISTING_EMPTY.clone(); let mut set_par = SET_EXISTING_EMPTY.clone(); set_seq.extend(SET_EXTENSION.iter().copied()); set_par.par_extend(SET_EXTENSION.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } #[test] fn set_seq_par_equivalence_existing_extend_empty() { let expected = SET_EXISTING.clone(); let mut set_seq = SET_EXISTING.clone(); let mut set_par = SET_EXISTING.clone(); set_seq.extend(SET_EXTENSION_EMPTY.iter().copied()); set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } #[test] fn set_seq_par_equivalence_existing_extend() { let expected = SET.clone(); let mut set_seq = SET_EXISTING.clone(); let mut set_par = SET_EXISTING.clone(); set_seq.extend(SET_EXTENSION.iter().copied()); set_par.par_extend(SET_EXTENSION.par_iter().copied()); assert_eq3!(set_seq, set_par, expected); } static SET_A: LazyLock> = LazyLock::new(|| ['a', 'b', 'c', 'd'].iter().copied().collect()); static SET_B: LazyLock> = LazyLock::new(|| ['a', 'b', 'e', 'f'].iter().copied().collect()); static SET_DIFF_AB: LazyLock> = LazyLock::new(|| ['c', 'd'].iter().copied().collect()); static SET_DIFF_BA: LazyLock> = LazyLock::new(|| ['e', 'f'].iter().copied().collect()); static SET_SYMM_DIFF_AB: LazyLock> = LazyLock::new(|| ['c', 'd', 'e', 'f'].iter().copied().collect()); static SET_INTERSECTION_AB: LazyLock> = LazyLock::new(|| ['a', 'b'].iter().copied().collect()); static SET_UNION_AB: LazyLock> = LazyLock::new(|| ['a', 'b', 'c', 'd', 'e', 'f'].iter().copied().collect()); #[test] fn set_seq_par_equivalence_difference() { let diff_ab_seq = SET_A.difference(&*SET_B).copied().collect::>(); let diff_ab_par = SET_A .par_difference(&*SET_B) .copied() .collect::>(); assert_eq3!(diff_ab_seq, diff_ab_par, *SET_DIFF_AB); let diff_ba_seq = SET_B.difference(&*SET_A).copied().collect::>(); let diff_ba_par = SET_B .par_difference(&*SET_A) .copied() .collect::>(); assert_eq3!(diff_ba_seq, diff_ba_par, *SET_DIFF_BA); } #[test] fn set_seq_par_equivalence_symmetric_difference() { let symm_diff_ab_seq = SET_A .symmetric_difference(&*SET_B) .copied() .collect::>(); let symm_diff_ab_par = SET_A .par_symmetric_difference(&*SET_B) .copied() .collect::>(); assert_eq3!(symm_diff_ab_seq, symm_diff_ab_par, *SET_SYMM_DIFF_AB); } #[test] fn set_seq_par_equivalence_intersection() { let intersection_ab_seq = SET_A.intersection(&*SET_B).copied().collect::>(); let intersection_ab_par = SET_A .par_intersection(&*SET_B) .copied() .collect::>(); assert_eq3!( intersection_ab_seq, intersection_ab_par, *SET_INTERSECTION_AB ); } #[test] fn set_seq_par_equivalence_union() { let union_ab_seq = SET_A.union(&*SET_B).copied().collect::>(); let union_ab_par = SET_A.par_union(&*SET_B).copied().collect::>(); assert_eq3!(union_ab_seq, union_ab_par, *SET_UNION_AB); }