1use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
2use core::{fmt::Debug, hash::Hash, mem::ManuallyDrop, ptr::NonNull};
3
4use crate::length::{InvalidLength, SmallLen, ValidLength};
5
6#[cold]
7fn truncate_vec<T>(err: InvalidLength<T>, max_len: usize) -> Vec<T> {
8 let mut value = Vec::from(err.get_inner());
9 value.truncate(max_len);
10 value
11}
12
13#[repr(packed)]
17pub struct FixedArray<T, LenT: ValidLength = SmallLen> {
18 ptr: NonNull<T>,
19 len: LenT,
20}
21
22impl<T, LenT: ValidLength> FixedArray<T, LenT> {
23 #[must_use]
25 pub fn new() -> Self {
26 Self::empty()
27 }
28
29 #[must_use]
31 pub fn empty() -> Self {
32 Self {
33 ptr: NonNull::dangling(),
34 len: LenT::ZERO,
35 }
36 }
37
38 unsafe fn from_box(ptr: Box<[T]>, len: LenT) -> Self {
41 debug_assert_eq!(len.into().to_usize(), ptr.len());
42
43 let array_ptr = Box::into_raw(ptr).cast::<T>();
44 Self {
45 ptr: NonNull::new(array_ptr).expect("Box ptr != nullptr"),
46 len,
47 }
48 }
49
50 #[must_use]
52 pub fn from_vec_trunc(vec: Vec<T>) -> Self {
53 match vec.into_boxed_slice().try_into() {
54 Ok(v) => v,
55 Err(err) => Self::from_vec_trunc(truncate_vec(err, LenT::MAX.to_usize())),
56 }
57 }
58
59 #[must_use]
61 pub fn len(&self) -> LenT {
62 self.len
63 }
64
65 #[must_use]
67 pub fn is_empty(&self) -> bool {
68 self.len() == LenT::ZERO
69 }
70
71 #[must_use]
73 pub fn into_vec(self) -> Vec<T> {
74 self.into()
75 }
76
77 #[must_use]
79 pub fn into_boxed_slice(self) -> Box<[T]> {
80 self.into()
81 }
82
83 #[must_use]
85 pub fn as_slice(&self) -> &[T] {
86 self
87 }
88
89 #[must_use]
91 pub fn as_slice_mut(&mut self) -> &mut [T] {
92 self
93 }
94
95 pub(crate) unsafe fn as_box(&mut self) -> Box<[T]> {
100 let slice = self.as_slice_mut();
101
102 unsafe { Box::from_raw(slice) }
104 }
105}
106
107unsafe impl<T: Send, LenT: ValidLength> Send for FixedArray<T, LenT> {}
108unsafe impl<T: Sync, LenT: ValidLength> Sync for FixedArray<T, LenT> {}
109
110impl<T, LenT: ValidLength> core::ops::Deref for FixedArray<T, LenT> {
111 type Target = [T];
112 fn deref(&self) -> &Self::Target {
113 unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len().to_usize()) }
115 }
116}
117
118impl<T, LenT: ValidLength> core::ops::DerefMut for FixedArray<T, LenT> {
119 fn deref_mut(&mut self) -> &mut Self::Target {
120 unsafe { core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len().to_usize()) }
122 }
123}
124
125impl<T, LenT: ValidLength> Drop for FixedArray<T, LenT> {
126 fn drop(&mut self) {
127 unsafe { self.as_box() };
129 }
130}
131
132impl<T, LenT: ValidLength> Default for FixedArray<T, LenT> {
133 fn default() -> Self {
135 Self::empty()
136 }
137}
138
139impl<T: Clone, LenT: ValidLength> Clone for FixedArray<T, LenT> {
140 fn clone(&self) -> Self {
141 let ptr = self.as_slice().to_vec().into_boxed_slice();
142
143 unsafe { Self::from_box(ptr, self.len) }
145 }
146
147 #[allow(clippy::assigning_clones)]
148 fn clone_from(&mut self, source: &Self) {
149 if self.len() == source.len() {
150 self.clone_from_slice(source);
151 } else {
152 *self = source.clone();
153 }
154 }
155}
156
157impl<T, LenT: ValidLength> core::ops::Index<LenT> for FixedArray<T, LenT> {
158 type Output = T;
159 fn index(&self, index: LenT) -> &Self::Output {
160 &self.as_slice()[index.to_usize()]
161 }
162}
163
164impl<T, LenT: ValidLength> core::ops::IndexMut<LenT> for FixedArray<T, LenT> {
165 fn index_mut(&mut self, index: LenT) -> &mut Self::Output {
166 &mut self.as_slice_mut()[index.to_usize()]
167 }
168}
169
170impl<T: Hash, LenT: ValidLength> Hash for FixedArray<T, LenT> {
171 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
172 self.as_slice().hash(state);
173 }
174}
175
176impl<T: PartialEq, LenT: ValidLength> PartialEq for FixedArray<T, LenT> {
177 fn eq(&self, other: &Self) -> bool {
178 self.as_slice().eq(other.as_slice())
179 }
180}
181
182impl<T: Eq, LenT: ValidLength> Eq for FixedArray<T, LenT> {}
183
184impl<T: Debug, LenT: ValidLength> Debug for FixedArray<T, LenT> {
185 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
186 <[T] as Debug>::fmt(self, f)
187 }
188}
189
190impl<T, LenT: ValidLength> IntoIterator for FixedArray<T, LenT> {
191 type Item = <Vec<T> as IntoIterator>::Item;
192 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
193
194 fn into_iter(self) -> Self::IntoIter {
195 self.into_vec().into_iter()
196 }
197}
198
199impl<'a, T, LenT: ValidLength> IntoIterator for &'a FixedArray<T, LenT> {
200 type Item = <&'a [T] as IntoIterator>::Item;
201 type IntoIter = <&'a [T] as IntoIterator>::IntoIter;
202
203 fn into_iter(self) -> Self::IntoIter {
204 self.as_slice().iter()
205 }
206}
207
208impl<'a, T, LenT: ValidLength> IntoIterator for &'a mut FixedArray<T, LenT> {
209 type Item = <&'a mut [T] as IntoIterator>::Item;
210 type IntoIter = <&'a mut [T] as IntoIterator>::IntoIter;
211
212 fn into_iter(self) -> Self::IntoIter {
213 self.as_slice_mut().iter_mut()
214 }
215}
216
217impl<T, LenT: ValidLength> From<FixedArray<T, LenT>> for Box<[T]> {
218 fn from(value: FixedArray<T, LenT>) -> Self {
219 let mut value = ManuallyDrop::new(value);
220
221 unsafe { value.as_box() }
223 }
224}
225
226impl<T, LenT: ValidLength> From<FixedArray<T, LenT>> for Vec<T> {
227 fn from(value: FixedArray<T, LenT>) -> Self {
228 value.into_boxed_slice().into_vec()
229 }
230}
231
232impl<'a, T: Clone, LenT: ValidLength> From<&'a FixedArray<T, LenT>> for Cow<'a, [T]> {
233 fn from(value: &'a FixedArray<T, LenT>) -> Self {
234 Cow::Borrowed(value.as_slice())
235 }
236}
237
238impl<T: Clone, LenT: ValidLength> From<FixedArray<T, LenT>> for Cow<'_, [T]> {
239 fn from(value: FixedArray<T, LenT>) -> Self {
240 Cow::Owned(value.into_vec())
241 }
242}
243
244impl<T, LenT: ValidLength> From<FixedArray<T, LenT>> for Arc<[T]> {
245 fn from(value: FixedArray<T, LenT>) -> Self {
246 Arc::from(value.into_boxed_slice())
247 }
248}
249
250impl<T, LenT: ValidLength> TryFrom<Box<[T]>> for FixedArray<T, LenT> {
251 type Error = InvalidLength<T>;
252 fn try_from(boxed_array: Box<[T]>) -> Result<Self, Self::Error> {
253 let Some(len) = LenT::from_usize(boxed_array.len()) else {
254 return Err(InvalidLength::new(
255 core::any::type_name::<LenT>(),
256 boxed_array,
257 ));
258 };
259
260 Ok(unsafe { Self::from_box(boxed_array, len) })
262 }
263}
264
265macro_rules! impl_array_from {
266 ($($N:expr),*) => {
267 $(
268 impl<T, LenT: ValidLength> From<[T; $N]> for FixedArray<T, LenT> {
269 fn from(val: [T; $N]) -> Self {
270 Self::try_from(Box::from(val))
271 .unwrap_or_else(|_| unreachable!(concat!($N, " should be less than {}"), LenT::MAX))
272 }
273 }
274 )*
275 };
276}
277
278impl_array_from!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
279
280impl<T, LenT: ValidLength> AsRef<[T]> for FixedArray<T, LenT> {
281 fn as_ref(&self) -> &[T] {
282 self
283 }
284}
285
286#[cfg(feature = "serde")]
287impl<'de, T, LenT> serde::Deserialize<'de> for FixedArray<T, LenT>
288where
289 T: serde::Deserialize<'de>,
290 LenT: ValidLength,
291{
292 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
293 Self::try_from(Box::<[T]>::deserialize(deserializer)?).map_err(serde::de::Error::custom)
294 }
295}
296
297#[cfg(feature = "serde")]
298impl<T, LenT> serde::Serialize for FixedArray<T, LenT>
299where
300 T: serde::Serialize,
301 LenT: ValidLength,
302{
303 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
304 self.as_slice().serialize(serializer)
305 }
306}
307
308#[cfg(feature = "typesize")]
309impl<T: typesize::TypeSize, LenT: ValidLength> typesize::TypeSize for FixedArray<T, LenT> {
310 fn extra_size(&self) -> usize {
311 self.iter().map(T::get_size).sum()
312 }
313}