generic_array/ext_impls/
impl_alloc.rs1use alloc::{boxed::Box, vec::Vec};
2
3use crate::{ArrayLength, GenericArray, IntrusiveArrayBuilder, LengthError};
4
5impl<T, N: ArrayLength> TryFrom<Vec<T>> for GenericArray<T, N> {
6 type Error = crate::LengthError;
7
8 fn try_from(v: Vec<T>) -> Result<Self, Self::Error> {
9 if v.len() != N::USIZE {
10 return Err(crate::LengthError);
11 }
12
13 unsafe {
14 let mut destination = core::mem::MaybeUninit::<GenericArray<T, N>>::uninit();
15 let mut builder = IntrusiveArrayBuilder::new_alt(&mut destination);
16
17 builder.extend(v.into_iter());
18
19 Ok(builder.finish_and_assume_init())
20 }
21 }
22}
23
24impl<T, N: ArrayLength> GenericArray<T, N> {
25 /// Converts a `Box<GenericArray<T, N>>` into `Box<[T]>` without reallocating.
26 ///
27 /// This operation is O(1), constant-time regardless of the array length N.
28 #[inline]
29 pub fn into_boxed_slice(self: Box<GenericArray<T, N>>) -> Box<[T]> {
30 unsafe {
31 // SAFETY: Box ensures the array is properly aligned
32 Box::from_raw(core::ptr::slice_from_raw_parts_mut(
33 Box::into_raw(self) as *mut T,
34 N::USIZE,
35 ))
36 }
37 }
38
39 /// Converts a `Box<GenericArray<T, N>>` into `Vec<T>` without reallocating.
40 ///
41 /// This operation is O(1), constant-time regardless of the array length N.
42 #[inline]
43 pub fn into_vec(self: Box<GenericArray<T, N>>) -> Vec<T> {
44 Vec::from(self.into_boxed_slice())
45 }
46
47 /// Attempts to convert a `Box<[T]>` into `Box<GenericArray<T, N>>` without reallocating.
48 ///
49 /// This operation is O(1), constant-time regardless of the array length N.
50 #[inline]
51 pub fn try_from_boxed_slice(slice: Box<[T]>) -> Result<Box<GenericArray<T, N>>, LengthError> {
52 if slice.len() != N::USIZE {
53 return Err(LengthError);
54 }
55
56 Ok(unsafe { Box::from_raw(Box::into_raw(slice) as *mut _) })
57 }
58
59 /// Attempts to convert a `Vec<T>` into `Box<GenericArray<T, N>>` without reallocating.
60 ///
61 /// This operation is O(1) **if the `Vec` has the same length and capacity as `N`**,
62 /// otherwise it will be forced to call `Vec::shrink_to_fit` which is O(N),
63 /// where N is the number of elements.
64 #[inline]
65 pub fn try_from_vec(vec: Vec<T>) -> Result<Box<GenericArray<T, N>>, LengthError> {
66 Self::try_from_boxed_slice(vec.into_boxed_slice())
67 }
68
69 /// Alternative to `Box::<GenericArray<T, N>>::default()` that won't overflow the stack for very large arrays.
70 ///
71 /// The standard `Box::default()` calls `default` on the inner type, creating it on the stack,
72 /// and then moves it onto the heap. Optimized release builds often remove this step, but debug builds
73 /// may have issues.
74 #[inline]
75 pub fn default_boxed() -> Box<GenericArray<T, N>>
76 where
77 T: Default,
78 {
79 Box::<GenericArray<T, N>>::generate(|_| T::default())
80 }
81
82 /// Like [`GenericArray::try_from_iter`] but returns a `Box<GenericArray<T, N>>` instead.
83 pub fn try_boxed_from_iter<I>(iter: I) -> Result<Box<GenericArray<T, N>>, LengthError>
84 where
85 I: IntoIterator<Item = T>,
86 {
87 let mut iter = iter.into_iter();
88
89 // pre-checks
90 match iter.size_hint() {
91 // if the lower bound is greater than N, array will overflow
92 (n, _) if n > N::USIZE => return Err(LengthError),
93 // if the upper bound is smaller than N, array cannot be filled
94 (_, Some(n)) if n < N::USIZE => return Err(LengthError),
95 _ => {}
96 }
97
98 let mut v = Vec::with_capacity(N::USIZE);
99 v.extend((&mut iter).take(N::USIZE));
100
101 if v.len() != N::USIZE || iter.next().is_some() {
102 return Err(LengthError);
103 }
104
105 Ok(GenericArray::try_from_vec(v).unwrap())
106 }
107}
108
109impl<T, N: ArrayLength> TryFrom<Box<[T]>> for GenericArray<T, N> {
110 type Error = crate::LengthError;
111
112 #[inline]
113 fn try_from(value: Box<[T]>) -> Result<Self, Self::Error> {
114 Vec::from(value).try_into()
115 }
116}
117
118impl<T, N: ArrayLength> From<GenericArray<T, N>> for Box<[T]> {
119 #[inline]
120 fn from(value: GenericArray<T, N>) -> Self {
121 Box::new(value).into_boxed_slice()
122 }
123}
124
125impl<T, N: ArrayLength> From<GenericArray<T, N>> for Vec<T> {
126 #[inline]
127 fn from(value: GenericArray<T, N>) -> Self {
128 Box::<[T]>::from(value).into()
129 }
130}
131
132impl<T, N: ArrayLength> IntoIterator for Box<GenericArray<T, N>> {
133 type IntoIter = alloc::vec::IntoIter<T>;
134 type Item = T;
135
136 fn into_iter(self) -> Self::IntoIter {
137 GenericArray::into_vec(self).into_iter()
138 }
139}
140
141impl<T, N: ArrayLength> FromIterator<T> for Box<GenericArray<T, N>> {
142 /// Create a `Box<GenericArray>` from an iterator.
143 ///
144 /// Will panic if the number of elements is not exactly the array length.
145 ///
146 /// See [`GenericArray::try_boxed_from_iter]` for a fallible alternative.
147 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
148 match GenericArray::try_boxed_from_iter(iter) {
149 Ok(res) => res,
150 Err(_) => crate::from_iter_length_fail(N::USIZE),
151 }
152 }
153}
154
155use crate::functional::{FunctionalSequence, MappedGenericSequence};
156use crate::GenericSequence;
157
158unsafe impl<T, N: ArrayLength> GenericSequence<T> for Box<GenericArray<T, N>> {
159 type Length = N;
160 type Sequence = Box<GenericArray<T, N>>;
161
162 fn generate<F>(mut f: F) -> Self::Sequence
163 where
164 F: FnMut(usize) -> T,
165 {
166 unsafe {
167 use core::{
168 alloc::Layout,
169 mem::{size_of, MaybeUninit},
170 ptr,
171 };
172
173 // Box::new_uninit() is nightly-only
174 let ptr: *mut GenericArray<MaybeUninit<T>, N> = if size_of::<T>() == 0 {
175 ptr::NonNull::dangling().as_ptr()
176 } else {
177 alloc::alloc::alloc(Layout::new::<GenericArray<MaybeUninit<T>, N>>()).cast()
178 };
179
180 let mut builder = IntrusiveArrayBuilder::new(&mut *ptr);
181
182 {
183 let (builder_iter, position) = builder.iter_position();
184
185 builder_iter.enumerate().for_each(|(i, dst)| {
186 dst.write(f(i));
187 *position += 1;
188 });
189 }
190
191 builder.finish();
192
193 Box::from_raw(ptr.cast()) // assume_init
194 }
195 }
196}
197
198impl<T, U, N: ArrayLength> MappedGenericSequence<T, U> for Box<GenericArray<T, N>> {
199 type Mapped = Box<GenericArray<U, N>>;
200}
201
202impl<T, N: ArrayLength> FunctionalSequence<T> for Box<GenericArray<T, N>> where
203 Self: GenericSequence<T, Item = T, Length = N>
204{
205}