1use alloc::{boxed::Box, vec::Vec};
2
3use crate::{ArrayLength, GenericArray, IntrusiveArrayBuilder, LengthError};
4
5use core::{alloc::Layout, mem::MaybeUninit, ptr};
6
7struct IntrusiveBoxedArrayBuilder<T, N: ArrayLength> {
8 layout: Layout,
9 ptr: *mut GenericArray<MaybeUninit<T>, N>,
10 position: usize,
11}
12
13impl<T, N: ArrayLength> IntrusiveBoxedArrayBuilder<T, N> {
14 #[inline(always)]
15 unsafe fn iter_position(
16 &'_ mut self,
17 ) -> (core::slice::IterMut<'_, MaybeUninit<T>>, &'_ mut usize) {
18 ((&mut *self.ptr).iter_mut(), &mut self.position)
19 }
20
21 #[inline(always)]
22 unsafe fn finish(self) -> Box<GenericArray<T, N>> {
23 debug_assert!(self.position == N::USIZE);
24 let ptr = self.ptr;
25 core::mem::forget(self);
26 Box::from_raw(ptr.cast())
27 }
28}
29
30impl<T, N: ArrayLength> Drop for IntrusiveBoxedArrayBuilder<T, N> {
31 fn drop(&mut self) {
32 unsafe {
33 ptr::drop_in_place(
34 (&mut *self.ptr).get_unchecked_mut(..self.position)
35 as *mut [MaybeUninit<T>] as *mut [T],
36 );
37 alloc::alloc::dealloc(self.ptr.cast(), self.layout);
38 }
39 }
40}
41
42impl<T, N: ArrayLength> TryFrom<Vec<T>> for GenericArray<T, N> {
43 type Error = crate::LengthError;
44
45 fn try_from(v: Vec<T>) -> Result<Self, Self::Error> {
46 if v.len() != N::USIZE {
47 return Err(crate::LengthError);
48 }
49
50 unsafe {
51 let mut destination = core::mem::MaybeUninit::<GenericArray<T, N>>::uninit();
52 let mut builder = IntrusiveArrayBuilder::new_alt(&mut destination);
53
54 builder.extend(v.into_iter());
55
56 Ok(builder.finish_and_assume_init())
57 }
58 }
59}
60
61impl<T, N: ArrayLength> GenericArray<T, N> {
62 #[inline]
66 pub fn into_boxed_slice(self: Box<GenericArray<T, N>>) -> Box<[T]> {
67 unsafe {
68 Box::from_raw(core::ptr::slice_from_raw_parts_mut(
70 Box::into_raw(self) as *mut T,
71 N::USIZE,
72 ))
73 }
74 }
75
76 #[inline]
80 pub fn into_vec(self: Box<GenericArray<T, N>>) -> Vec<T> {
81 Vec::from(self.into_boxed_slice())
82 }
83
84 #[inline]
88 pub fn try_from_boxed_slice(slice: Box<[T]>) -> Result<Box<GenericArray<T, N>>, LengthError> {
89 if slice.len() != N::USIZE {
90 return Err(LengthError);
91 }
92
93 Ok(unsafe { Box::from_raw(Box::into_raw(slice) as *mut _) })
94 }
95
96 #[inline]
102 pub fn try_from_vec(vec: Vec<T>) -> Result<Box<GenericArray<T, N>>, LengthError> {
103 Self::try_from_boxed_slice(vec.into_boxed_slice())
104 }
105
106 #[inline]
112 pub fn default_boxed() -> Box<GenericArray<T, N>>
113 where
114 T: Default,
115 {
116 Box::<GenericArray<T, N>>::generate(|_| T::default())
117 }
118
119 pub fn try_boxed_from_iter<I>(iter: I) -> Result<Box<GenericArray<T, N>>, LengthError>
121 where
122 I: IntoIterator<Item = T>,
123 {
124 let mut iter = iter.into_iter();
125
126 match iter.size_hint() {
128 (n, _) if n > N::USIZE => return Err(LengthError),
130 (_, Some(n)) if n < N::USIZE => return Err(LengthError),
132 _ => {}
133 }
134
135 let mut v = Vec::with_capacity(N::USIZE);
136 v.extend((&mut iter).take(N::USIZE));
137
138 if v.len() != N::USIZE || iter.next().is_some() {
139 return Err(LengthError);
140 }
141
142 Ok(GenericArray::try_from_vec(v).unwrap())
143 }
144}
145
146impl<T, N: ArrayLength> TryFrom<Box<[T]>> for GenericArray<T, N> {
147 type Error = crate::LengthError;
148
149 #[inline]
150 fn try_from(value: Box<[T]>) -> Result<Self, Self::Error> {
151 Vec::from(value).try_into()
152 }
153}
154
155impl<T, N: ArrayLength> From<GenericArray<T, N>> for Box<[T]> {
156 #[inline]
157 fn from(value: GenericArray<T, N>) -> Self {
158 Box::new(value).into_boxed_slice()
159 }
160}
161
162impl<T, N: ArrayLength> From<GenericArray<T, N>> for Vec<T> {
163 #[inline]
164 fn from(value: GenericArray<T, N>) -> Self {
165 Box::<[T]>::from(value).into()
166 }
167}
168
169impl<T, N: ArrayLength> IntoIterator for Box<GenericArray<T, N>> {
170 type IntoIter = alloc::vec::IntoIter<T>;
171 type Item = T;
172
173 fn into_iter(self) -> Self::IntoIter {
174 GenericArray::into_vec(self).into_iter()
175 }
176}
177
178impl<T, N: ArrayLength> FromIterator<T> for Box<GenericArray<T, N>> {
179 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
185 match GenericArray::try_boxed_from_iter(iter) {
186 Ok(res) => res,
187 Err(_) => crate::from_iter_length_fail(N::USIZE),
188 }
189 }
190}
191
192use crate::functional::{FunctionalSequence, MappedGenericSequence};
193use crate::GenericSequence;
194
195unsafe impl<T, N: ArrayLength> GenericSequence<T> for Box<GenericArray<T, N>> {
196 type Length = N;
197 type Sequence = Box<GenericArray<T, N>>;
198
199 fn generate<F>(mut f: F) -> Self::Sequence
200 where
201 F: FnMut(usize) -> T,
202 {
203 unsafe {
204 let layout = Layout::new::<GenericArray<MaybeUninit<T>, N>>();
205
206 if layout.size() == 0 {
207 return Box::from_raw(ptr::NonNull::dangling().as_ptr());
208 }
209
210 let raw_ptr = alloc::alloc::alloc(layout);
211
212 if raw_ptr.is_null() {
213 alloc::alloc::handle_alloc_error(layout);
214 }
215
216 let mut builder = IntrusiveBoxedArrayBuilder {
217 layout,
218 ptr: raw_ptr.cast(),
219 position: 0,
220 };
221
222 {
223 let (builder_iter, position) = builder.iter_position();
224
225 builder_iter.enumerate().for_each(|(i, dst)| {
226 dst.write(f(i));
227 *position += 1;
228 });
229 }
230
231 builder.finish()
232 }
233 }
234}
235
236impl<T, U, N: ArrayLength> MappedGenericSequence<T, U> for Box<GenericArray<T, N>> {
237 type Mapped = Box<GenericArray<U, N>>;
238}
239
240impl<T, N: ArrayLength> FunctionalSequence<T> for Box<GenericArray<T, N>> where
241 Self: GenericSequence<T, Item = T, Length = N>
242{
243}
244
245use crate::sequence::{FallibleGenericSequence, FromFallibleIterator};
246
247impl<T, N: ArrayLength> FromFallibleIterator<T> for Box<GenericArray<T, N>> {
248 fn from_fallible_iter<I, E>(iter: I) -> Result<Self, E>
249 where
250 I: IntoIterator<Item = Result<T, E>>,
251 {
252 let mut iter = iter.into_iter();
253 let mut v = Vec::with_capacity(N::USIZE);
254 for item in (&mut iter).take(N::USIZE) {
255 v.push(item?);
256 }
257 if v.len() != N::USIZE || iter.next().is_some() {
258 crate::from_iter_length_fail(N::USIZE)
259 } else {
260 Ok(GenericArray::try_from_vec(v).unwrap())
261 }
262 }
263}
264
265unsafe impl<T, N: ArrayLength> FallibleGenericSequence<T> for Box<GenericArray<T, N>> {
266 type Error = crate::AllocError;
267
268 fn try_generate<F, E>(mut f: F) -> Result<Result<Self::Sequence, E>, crate::AllocError>
269 where
270 F: FnMut(usize) -> Result<T, E>,
271 {
272 unsafe {
273 let layout = Layout::new::<GenericArray<MaybeUninit<T>, N>>();
274
275 if layout.size() == 0 {
276 return Ok(Ok(Box::from_raw(ptr::NonNull::dangling().as_ptr())));
277 }
278
279 let raw_ptr = alloc::alloc::alloc(layout);
280
281 if raw_ptr.is_null() {
282 return Err(crate::AllocError);
283 }
284
285 let mut builder = IntrusiveBoxedArrayBuilder {
286 layout,
287 ptr: raw_ptr.cast(),
288 position: 0,
289 };
290
291 let (builder_iter, position) = builder.iter_position();
292
293 if let Err(e) = builder_iter
294 .enumerate()
295 .try_for_each(|(i, dst)| match f(i) {
296 Ok(value) => {
297 dst.write(value);
298 *position += 1;
299 Ok(())
300 }
301 Err(e) => Err(e),
302 })
303 {
304 drop(builder);
305 return Ok(Err(e));
306 }
307
308 Ok(Ok(builder.finish()))
309 }
310 }
311}