1use core::{
2 cell::Cell,
3 fmt::{Debug, Display},
4 marker::{PhantomData, PhantomPinned},
5 mem::MaybeUninit,
6 pin::Pin,
7};
8
9use crate::{
10 internal::{BaseStorage, PeekIter},
11 merge_iter::{DefaultBuilder, DefaultMergeIter},
12 storage::{Storage as _, debug_formatter},
13};
14
15#[derive(Debug, Clone, Copy)]
17pub struct ArrayCapacityOverflow;
18
19impl Display for ArrayCapacityOverflow {
20 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21 f.write_str("Capacity overflow")
22 }
23}
24
25#[rustversion::since(1.81)]
26impl core::error::Error for ArrayCapacityOverflow {}
27
28pub struct ArrayStorage<const CAP: usize, IT: Iterator> {
30 storage: [MaybeUninit<PeekIter<IT>>; CAP],
31 heap: [MaybeUninit<*mut PeekIter<IT>>; CAP],
32 len: Cell<usize>,
33 _p: PhantomPinned,
34}
35
36impl<const CAP: usize, IT: Iterator> Debug for ArrayStorage<CAP, IT>
37where
38 PeekIter<IT>: Debug,
39{
40 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41 f.debug_struct("ArrayStorage")
42 .field("CAP", &CAP)
43 .field("len", &self.len)
44 .field("storage", &
45 unsafe {
47 core::slice::from_raw_parts(
48 self.storage.as_ptr().cast::<PeekIter<IT>>(),
49 self.len(),
50 )
51 })
52 .finish_non_exhaustive()
53 }
54}
55
56#[inline(always)]
57const fn uninit_array<const CAP: usize, T>() -> [MaybeUninit<T>; CAP] {
58 unsafe { MaybeUninit::<[MaybeUninit<T>; CAP]>::uninit().assume_init() }
60}
61
62impl<IT: Iterator> ArrayStorage<0, IT> {
63 #[must_use]
65 #[inline(always)]
66 pub const fn with_capacity<const CAP: usize>() -> ArrayStorage<CAP, IT> {
67 ArrayStorage::new()
68 }
69}
70
71impl<const CAP: usize, IT: Iterator> ArrayStorage<CAP, IT> {
72 #[must_use]
90 #[inline(always)]
91 pub const fn new() -> Self {
92 Self {
93 storage: uninit_array(),
94 heap: uninit_array(),
95 len: Cell::new(0),
96 _p: PhantomPinned,
97 }
98 }
99
100 #[must_use]
114 #[inline]
115 pub fn from_arr<T: IntoIterator<IntoIter = IT>>(iters: [T; CAP]) -> Self {
116 let mut res = Self::new();
117 res.extend(iters);
118 res
119 }
120
121 #[inline]
123 pub fn len(&self) -> usize {
124 self.len.get()
125 }
126
127 #[inline]
129 pub const fn capacity(&self) -> usize {
130 CAP
131 }
132
133 #[inline]
135 pub fn is_empty(&self) -> bool {
136 self.len() == 0
137 }
138
139 pub fn push<Iter>(&mut self, iter: Iter)
145 where
146 Iter: IntoIterator<IntoIter = IT>,
147 {
148 self.try_push(iter).unwrap();
149 }
150
151 pub fn try_push<Iter>(&mut self, iter: Iter) -> Result<(), ArrayCapacityOverflow>
155 where
156 Iter: IntoIterator<IntoIter = IT>,
157 {
158 if let Some(peek_iter) = PeekIter::new_from_iter(iter) {
159 let len = self.len.get();
160 if len >= CAP {
161 return Err(ArrayCapacityOverflow);
162 }
163 self.storage[len].write(peek_iter);
164 self.len.set(len.checked_add(1).expect("unreachable"));
165 }
166 Ok(())
167 }
168
169 #[must_use]
185 pub fn into_builder(self: Pin<&mut Self>) -> DefaultBuilder<InternalArrayStorage<'_, IT>> {
186 let len = self.len.replace(0);
187 debug_assert!(len <= CAP);
188 let (storage, heap) = {
189 let mut_ref = unsafe { Pin::get_unchecked_mut(self) };
194 (
195 mut_ref.storage.as_mut_ptr().cast::<PeekIter<IT>>(),
196 mut_ref.heap.as_mut_ptr().cast::<*mut PeekIter<IT>>(),
197 )
198 };
199 for i in 0..len {
200 unsafe {
205 heap.add(i).write(storage.add(i));
206 }
207 }
208 InternalArrayStorage {
209 heap,
210 len,
211 _p: PhantomData,
212 }
213 .into_builder()
214 }
215
216 #[must_use]
220 pub fn build(self: Pin<&mut Self>) -> DefaultMergeIter<InternalArrayStorage<'_, IT>>
221 where
222 IT::Item: Ord,
223 {
224 self.into_builder().build()
225 }
226}
227
228impl<const CAP: usize, IT, Item> FromIterator<Item> for ArrayStorage<CAP, IT>
229where
230 IT: Iterator,
231 Item: IntoIterator<IntoIter = IT>,
232{
233 fn from_iter<T: IntoIterator<Item = Item>>(iter: T) -> Self {
234 let mut res = Self::new();
235 res.extend(iter);
236 res
237 }
238}
239
240impl<const CAP: usize, IT: Iterator, A> Extend<A> for ArrayStorage<CAP, IT>
241where
242 A: IntoIterator<IntoIter = IT>,
243{
244 fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
245 for item in iter {
246 self.push(item);
247 }
248 }
249}
250
251impl<const CAP: usize, IT: Iterator> Default for ArrayStorage<CAP, IT> {
252 #[inline]
253 fn default() -> Self {
254 Self::new()
255 }
256}
257
258impl<const CAP: usize, IT: Iterator> Drop for ArrayStorage<CAP, IT> {
259 fn drop(&mut self) {
260 for i in 0..self.len.replace(0) {
266 unsafe {
271 self.storage[i].assume_init_drop();
272 }
273 }
274 }
275}
276
277pub struct InternalArrayStorage<'a, IT: Iterator> {
280 heap: *mut *mut PeekIter<IT>,
281 len: usize,
282 _p: PhantomData<Pin<&'a mut ArrayStorage<1, IT>>>,
285}
286
287unsafe impl<IT: Iterator> BaseStorage for InternalArrayStorage<'_, IT> {
288 type IT = IT;
289
290 #[inline]
291 fn heap(&self) -> *mut *mut PeekIter<IT> {
292 self.heap
293 }
294
295 #[inline]
296 fn len(&self) -> usize {
297 self.len
298 }
299
300 #[inline]
301 unsafe fn set_len(&mut self, new_len: usize) {
302 self.len = new_len;
303 }
304}
305
306impl<IT: Iterator> Debug for InternalArrayStorage<'_, IT>
307where
308 PeekIter<<Self as BaseStorage>::IT>: Debug,
309{
310 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
311 f.debug_struct("InternalArrayStorage")
312 .field("len", &self.len)
313 .field("storage", &debug_formatter(self))
314 .finish_non_exhaustive()
315 }
316}
317
318impl<IT: Iterator> Drop for InternalArrayStorage<'_, IT> {
319 fn drop(&mut self) {
320 crate::storage::StorageOps::clear(self);
321 }
323}
324
325unsafe impl<'a, IT> Send for InternalArrayStorage<'a, IT>
329where
330 IT: Iterator,
331 Pin<&'a mut ArrayStorage<1, IT>>: Send,
332{
333}
334
335unsafe impl<'a, IT> Sync for InternalArrayStorage<'a, IT>
337where
338 IT: Iterator,
339 Pin<&'a mut ArrayStorage<1, IT>>: Sync,
340{
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn capacity_overflow() {
349 let mut s: ArrayStorage<1, _> = ArrayStorage::default();
350 assert_eq!(s.len(), 0);
351 assert!(s.is_empty());
352 s.push([1, 2, 3]);
353 assert_eq!(s.len(), 1);
354 assert!(!s.is_empty());
355 assert!(matches!(s.try_push([4, 5, 6]), Err(ArrayCapacityOverflow)));
356 }
357}