1use core::hash::BuildHasher;
4use core::hash::Hash;
5
6use crate::Arena;
7use crate::collections::HashMap;
8use crate::collections::HashSet;
9use crate::vec::Vec;
10
11pub trait FromIteratorIn<T> {
16 type Alloc;
18
19 fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self
21 where
22 I: IntoIterator<Item = T>;
23}
24
25impl<'arena, T, A: Arena> FromIteratorIn<T> for Vec<'arena, T, A> {
26 type Alloc = &'arena A;
27
28 #[inline]
29 fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self
30 where
31 I: IntoIterator<Item = T>,
32 {
33 let mut collection = Self::new_in(alloc);
34 collection.extend(iter);
35 collection
36 }
37}
38
39impl<'arena, K, V, A, S> FromIteratorIn<(K, V)> for HashMap<'arena, K, V, A, S>
40where
41 K: Eq + Hash,
42 S: BuildHasher + Default,
43 A: Arena,
44{
45 type Alloc = &'arena A;
46
47 #[inline]
48 fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self
49 where
50 I: IntoIterator<Item = (K, V)>,
51 {
52 let mut collection = Self::with_hasher_in(S::default(), alloc);
53 collection.extend(iter);
54 collection
55 }
56}
57
58impl<'arena, T, A, S> FromIteratorIn<T> for HashSet<'arena, T, A, S>
59where
60 T: Eq + Hash,
61 S: BuildHasher + Default,
62 A: Arena,
63{
64 type Alloc = &'arena A;
65
66 #[inline]
67 fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self
68 where
69 I: IntoIterator<Item = T>,
70 {
71 let mut collection = Self::with_hasher_in(S::default(), alloc);
72 collection.extend(iter);
73 collection
74 }
75}
76
77pub trait CollectIn: Iterator + Sized {
85 #[inline]
87 fn collect_in<C>(self, alloc: C::Alloc) -> C
88 where
89 C: FromIteratorIn<Self::Item>,
90 {
91 C::from_iter_in(self, alloc)
92 }
93}
94
95impl<I: Iterator> CollectIn for I {}
96
97#[cfg(feature = "rayon")]
98pub use parallel::ParallelCollectIn;
99
100#[cfg(feature = "rayon")]
101mod parallel {
102 use rayon::iter::IndexedParallelIterator;
103 use rayon::iter::IntoParallelRefMutIterator;
104 use rayon::iter::ParallelIterator;
105
106 use crate::Arena;
107 use crate::vec::Vec;
108
109 pub trait ParallelCollectIn: IndexedParallelIterator
116 where
117 Self::Item: Send,
118 {
119 fn collect_in<A>(self, arena: &A) -> Vec<'_, Self::Item, A>
121 where
122 A: Arena + Sync,
123 {
124 let length = self.len();
125 let mut collection = Vec::with_capacity_in(length, arena);
126
127 collection.spare_capacity_mut()[..length].par_iter_mut().zip(self).for_each(|(slot, item)| {
128 slot.write(item);
129 });
130
131 unsafe { collection.set_len(length) };
133
134 collection
135 }
136 }
137
138 impl<I: IndexedParallelIterator> ParallelCollectIn for I where I::Item: Send {}
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use crate::arena::LocalArena;
145
146 #[test]
147 fn collect_in_vec() {
148 let arena = LocalArena::new();
149 let collected: Vec<'_, i32, LocalArena> = (0..5).collect_in(&arena);
150
151 assert_eq!(collected.as_slice(), &[0, 1, 2, 3, 4]);
152 }
153
154 #[test]
155 fn collect_in_hashset_deduplicates() {
156 let arena = LocalArena::new();
157 let collected: HashSet<'_, i32, LocalArena> = [1, 2, 2, 3].into_iter().collect_in(&arena);
158
159 assert_eq!(collected.len(), 3);
160 assert!(collected.contains(&2));
161 }
162
163 #[test]
164 fn collect_in_hashmap() {
165 let arena = LocalArena::new();
166 let collected: HashMap<'_, i32, i32, LocalArena> = [(1, 10), (2, 20)].into_iter().collect_in(&arena);
167
168 assert_eq!(collected.get(&2), Some(&20));
169 }
170}