1#![no_std]
2#![doc = include_str!("../README.md")]
3
4use core::ops::Deref;
5use core::ops::DerefMut;
6
7#[cfg(feature = "serde")]
9mod serde_impl;
10
11#[cfg(feature = "defmt")]
13mod defmt_impl;
14
15#[repr(C)]
17#[derive(Debug, Clone, Copy)]
18#[cfg_attr(
19 feature = "postcard_max_size",
20 derive(postcard::experimental::max_size::MaxSize)
21)]
22pub struct ArrayPlusExtra<T, const N: usize, const EXTRA: usize> {
23 data: [T; N],
24 extra: [T; EXTRA],
25}
26
27impl<T, const N: usize, const EXTRA: usize> ArrayPlusExtra<T, N, EXTRA>
28where
29 T: Copy,
30{
31 #[inline]
33 pub const fn new(value: T) -> Self {
34 Self {
35 data: [value; N],
36 extra: [value; EXTRA],
37 }
38 }
39}
40
41impl<T, const N: usize, const EXTRA: usize> ArrayPlusExtra<T, N, EXTRA> {
42 #[inline]
45 pub const fn as_slice(&self) -> &[T] {
46 unsafe { core::slice::from_raw_parts(self as *const _ as *const T, N + EXTRA) }
49 }
50
51 #[inline]
54 pub const fn as_mut_slice(&mut self) -> &mut [T] {
55 unsafe { core::slice::from_raw_parts_mut(self as *mut _ as *mut T, N + EXTRA) }
58 }
59}
60
61impl<T, const N: usize, const EXTRA: usize> Deref for ArrayPlusExtra<T, N, EXTRA> {
62 type Target = [T];
63
64 #[inline(always)]
65 fn deref(&self) -> &Self::Target {
66 self.as_slice()
67 }
68}
69
70impl<T, const N: usize, const EXTRA: usize> DerefMut for ArrayPlusExtra<T, N, EXTRA> {
71 #[inline(always)]
72 fn deref_mut(&mut self) -> &mut Self::Target {
73 self.as_mut_slice()
74 }
75}
76
77impl<T, const N: usize, const EXTRA: usize> PartialEq for ArrayPlusExtra<T, N, EXTRA>
79where
80 T: PartialEq,
81{
82 #[inline]
83 fn eq(&self, other: &Self) -> bool {
84 self[..] == other[..]
85 }
86}
87
88impl<T, const N: usize, const EXTRA: usize> Eq for ArrayPlusExtra<T, N, EXTRA> where T: Eq {}
90
91impl<T, const N: usize, const EXTRA: usize> core::hash::Hash for ArrayPlusExtra<T, N, EXTRA>
93where
94 T: core::hash::Hash,
95{
96 #[inline]
97 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
98 self[..].hash(state);
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 extern crate std;
108 use std::format;
109
110 #[test]
112 fn test_extra_zero_with_n_zero() {
113 let arr: ArrayPlusExtra<i32, 0, 0> = ArrayPlusExtra::new(42);
114 assert_eq!(arr.len(), 0);
116 }
117
118 #[test]
119 fn test_extra_zero_with_n_five() {
120 let mut arr: ArrayPlusExtra<i32, 5, 0> = ArrayPlusExtra::new(42);
121 assert_eq!(arr.len(), 5);
123 for i in 0..5 {
125 assert_eq!(arr[i], 42);
126 }
127 arr[4] = 100;
129 assert_eq!(arr[4], 100);
130 }
131
132 #[test]
134 fn test_extra_one_with_n_zero() {
135 let mut arr: ArrayPlusExtra<i32, 0, 1> = ArrayPlusExtra::new(99);
136 assert_eq!(arr.len(), 1);
138 assert_eq!(arr[0], 99);
139 arr[0] = 100;
140 assert_eq!(arr[0], 100);
141 }
142
143 #[test]
144 fn test_extra_one_with_n_five() {
145 let arr: ArrayPlusExtra<i32, 5, 1> = ArrayPlusExtra::new(42);
146 assert_eq!(arr.len(), 6);
148 for i in 0..6 {
150 assert_eq!(arr[i], 42);
151 }
152 }
153
154 #[test]
155 fn test_extra_one_deref_mut() {
156 let mut arr: ArrayPlusExtra<i32, 4, 1> = ArrayPlusExtra::new(0);
157 assert_eq!(arr.len(), 5);
159 for i in 0..5 {
161 arr[i] = i as i32;
162 }
163 for i in 0..5 {
165 assert_eq!(arr[i], i as i32);
166 }
167 }
168
169 #[test]
171 fn test_extra_three_with_n_two() {
172 let mut arr: ArrayPlusExtra<u32, 2, 3> = ArrayPlusExtra::new(7);
173 assert_eq!(arr.len(), 5);
175 for i in 0..5 {
177 assert_eq!(arr[i], 7);
178 }
179 arr[0] = 10; arr[1] = 20; arr[2] = 30; arr[3] = 40; arr[4] = 50; assert_eq!(arr[0], 10);
187 assert_eq!(arr[1], 20);
188 assert_eq!(arr[2], 30);
189 assert_eq!(arr[3], 40);
190 assert_eq!(arr[4], 50);
191 }
192
193 #[test]
194 fn test_extra_ten_with_n_ten() {
195 let mut arr: ArrayPlusExtra<u64, 10, 10> = ArrayPlusExtra::new(0);
196 assert_eq!(arr.len(), 20);
198 arr[0] = 1;
200 arr[9] = 9; arr[10] = 10; arr[19] = 19; assert_eq!(arr[0], 1);
205 assert_eq!(arr[9], 9);
206 assert_eq!(arr[10], 10);
207 assert_eq!(arr[19], 19);
208 }
209
210 #[test]
211 fn test_extra_fifty_large() {
212 let mut arr: ArrayPlusExtra<u8, 50, 50> = ArrayPlusExtra::new(1);
213 assert_eq!(arr.len(), 100);
215 assert_eq!(arr[0], 1);
217 assert_eq!(arr[25], 1); assert_eq!(arr[49], 1); assert_eq!(arr[50], 1); assert_eq!(arr[75], 1); assert_eq!(arr[99], 1); arr[99] = 255;
224 assert_eq!(arr[99], 255);
225 }
226
227 #[test]
229 fn test_different_types_various_extra() {
230 let arr_u8: ArrayPlusExtra<u8, 2, 2> = ArrayPlusExtra::new(255);
232 assert_eq!(arr_u8.len(), 4);
233 assert_eq!(arr_u8[3], 255);
234
235 let arr_u64: ArrayPlusExtra<u64, 2, 3> = ArrayPlusExtra::new(u64::MAX);
237 assert_eq!(arr_u64.len(), 5);
238 assert_eq!(arr_u64[4], u64::MAX);
239
240 let mut arr_f64: ArrayPlusExtra<f64, 1, 5> = ArrayPlusExtra::new(1.5);
242 assert_eq!(arr_f64.len(), 6);
243 arr_f64[5] = 2.5;
244 assert_eq!(arr_f64[5], 2.5);
245 }
246
247 #[test]
248 fn test_slice_iteration_various_extra() {
249 let mut arr: ArrayPlusExtra<i32, 3, 1> = ArrayPlusExtra::new(0);
251 assert_eq!(arr.len(), 4);
252 arr[0] = 10;
253 arr[1] = 20;
254 arr[2] = 30;
255 arr[3] = 40;
256
257 let sum: i32 = arr.iter().sum();
259 assert_eq!(sum, 100);
260
261 for elem in arr.iter_mut() {
263 *elem += 1;
264 }
265 assert_eq!(arr[0], 11);
266 assert_eq!(arr[3], 41);
267
268 let mut arr2: ArrayPlusExtra<i32, 2, 5> = ArrayPlusExtra::new(1);
270 assert_eq!(arr2.len(), 7);
271 let sum2: i32 = arr2.iter().sum();
272 assert_eq!(sum2, 7);
273
274 for elem in arr2.iter_mut() {
275 *elem *= 2;
276 }
277 for i in 0..7 {
278 assert_eq!(arr2[i], 2);
279 }
280 }
281
282 #[test]
284 fn test_debug() {
285 let arr: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(42);
286 let debug_str = format!("{:?}", arr);
287 assert!(debug_str.contains("42"));
289 }
290
291 #[test]
292 #[allow(clippy::clone_on_copy)]
293 fn test_clone() {
294 let arr: ArrayPlusExtra<i32, 2, 2> = ArrayPlusExtra::new(5);
295 let cloned = arr.clone();
296 assert_eq!(arr[0], cloned[0]);
297 assert_eq!(arr.len(), cloned.len());
298 for i in 0..4 {
299 assert_eq!(arr[i], cloned[i]);
300 }
301 }
302
303 #[test]
304 fn test_partial_eq() {
305 let arr1: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(42);
306 let arr2: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(42);
307 let arr3: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(99);
308
309 assert_eq!(arr1, arr2);
311 assert_ne!(arr1, arr3);
313 }
314
315 #[test]
316 fn test_eq_reflexive() {
317 let arr: ArrayPlusExtra<i32, 3, 2> = ArrayPlusExtra::new(7);
318 assert_eq!(arr, arr);
319 }
320
321 #[test]
322 fn test_hash() {
323 use core::hash::{Hash, Hasher};
324 use std::collections::hash_map::DefaultHasher;
325
326 let arr1: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(42);
327 let arr2: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(42);
328 let arr3: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(99);
329
330 let mut hasher1 = DefaultHasher::new();
331 let mut hasher2 = DefaultHasher::new();
332 let mut hasher3 = DefaultHasher::new();
333
334 arr1.hash(&mut hasher1);
335 arr2.hash(&mut hasher2);
336 arr3.hash(&mut hasher3);
337
338 assert_eq!(hasher1.finish(), hasher2.finish());
340 assert_ne!(hasher1.finish(), hasher3.finish());
342 }
343
344 #[test]
345 fn test_copy() {
346 let arr: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(10);
347 let copied = arr; assert_eq!(arr[0], 10);
350 assert_eq!(copied[0], 10);
351 }
352
353 #[test]
355 fn test_as_slice_const_fn() {
356 const ARR: ArrayPlusExtra<i32, 2, 1> = ArrayPlusExtra::new(42);
357 const SLICE: &[i32] = ARR.as_slice();
358 const LEN: usize = SLICE.len();
359
360 assert_eq!(LEN, 3);
361 assert_eq!(SLICE[0], 42);
362 assert_eq!(SLICE[1], 42);
363 assert_eq!(SLICE[2], 42);
364 }
365
366 #[test]
367 fn test_const_creation_and_slicing() {
368 const ARR: ArrayPlusExtra<u8, 5, 3> = ArrayPlusExtra::new(255);
369 const SLICE: &[u8] = ARR.as_slice();
370 const FIRST: u8 = SLICE[0];
371 const LAST_INDEX: usize = SLICE.len() - 1;
372
373 assert_eq!(FIRST, 255);
374 assert_eq!(SLICE.len(), 8);
375 assert_eq!(SLICE[LAST_INDEX], 255);
376 }
377
378 #[test]
379 fn test_as_slice_method() {
380 let arr: ArrayPlusExtra<i32, 3, 2> = ArrayPlusExtra::new(7);
381 let slice = arr.as_slice();
382
383 assert_eq!(slice.len(), 5);
384 for &val in slice {
385 assert_eq!(val, 7);
386 }
387 }
388
389 #[test]
390 fn test_as_mut_slice_method() {
391 let mut arr: ArrayPlusExtra<i32, 2, 2> = ArrayPlusExtra::new(0);
392 let slice = arr.as_mut_slice();
393
394 slice[0] = 10;
395 slice[1] = 20;
396 slice[2] = 30;
397 slice[3] = 40;
398
399 assert_eq!(arr[0], 10);
400 assert_eq!(arr[1], 20);
401 assert_eq!(arr[2], 30);
402 assert_eq!(arr[3], 40);
403 }
404
405 #[test]
406 fn test_const_zero_sized() {
407 const ARR: ArrayPlusExtra<i32, 0, 0> = ArrayPlusExtra::new(42);
408 const SLICE: &[i32] = ARR.as_slice();
409 const LEN: usize = SLICE.len();
410
411 assert_eq!(LEN, 0);
412 }
413}