Skip to main content

nyarray/
array.rs

1//! stack-allocated array structure.
2//! similar to `Vec` in functionality, except [`Array`] lives on the 'stack',
3//! lending it well for scratch arrays.
4//! 
5//! this structure is basically a lightweight wrapper over a simple `[T; N]` array type.
6//! 
7//! ## examples
8//! 
9//! ```
10//! # use nyarray::array::Array;
11//! let mut array = Array::<16, _>::new(); // new array with capacity of 16
12//! 
13//! // `Array` functions very similarly to `Vec`.
14//! 
15//! array.push(1);
16//! array.push(2);
17//!
18//! assert_eq!(array.len(), 2);
19//! assert_eq!(array[0], 1);
20//! 
21//! assert_eq!(array.pop(), Some(2));
22//! assert_eq!(array.len(), 1);
23//! 
24//! array[0] = 7;
25//! assert_eq!(array[0], 7);
26//! 
27//! array.extend([1, 2, 3]);
28//! 
29//! for x in &array {
30//!     println!("{x}");
31//! }
32//! 
33//! assert_eq!(array, [7, 1, 2, 3]);
34//! ```
35//! 
36//! note that, while the terminology "stack-allocated" is used here, one can
37//! easily allocate this structure onto the heap like so:
38//! 
39//! ```
40//! # use nyarray::array::Array;
41//! # use std::boxed::Box;
42//! let array = Box::new(Array::<16, ()>::new());
43//! ```
44//! 
45//! of course, at this point, one should consider using `Vec` or similar.
46
47use core::mem::ManuallyDrop;
48
49/// stack-allocated array. see [module level documentation](self) for more.
50pub struct Array<const N: usize, T> {
51	buf: [core::mem::MaybeUninit<T>; N],
52	len: usize,
53}
54
55impl<const N: usize, T> Array<N, T> {
56	/// create a new [`Array`].
57	/// 
58	/// ## examples
59	/// 
60	/// ```
61	/// # use nyarray::array::Array;
62	/// let array = Array::<16, ()>::new(); // array with capacity of 16
63	/// ```
64	#[inline]
65	pub const fn new() -> Self {
66		Self {
67			buf: [const { core::mem::MaybeUninit::uninit() }; N],
68			len: 0,
69		}
70	}
71
72	/// construct an array from a possibly uninitialized array.
73	/// 
74	/// ## safety
75	/// 
76	/// `buf[0..len]` must be fully initialized memory.
77	/// 
78	/// ## examples
79	/// 
80	/// this can be useful in combination with [`Self::into_parts_len()`] to
81	/// reconstruct the array after taking it apart for whatever reason.
82	/// 
83	/// ```
84	/// # use nyarray::array;
85	/// # use nyarray::array::Array;
86	/// let array = array![1, 2, 3 => 3];
87	/// 
88	/// let (buf, len) = array.into_parts_len();
89	/// 
90	/// // do whatever to `buf`
91	/// 
92	/// let array = unsafe { Array::from_parts_len(buf, len) };
93	/// ```
94	#[inline]
95	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
96	pub const unsafe fn from_parts_len(buf: [core::mem::MaybeUninit<T>; N], len: usize) -> Self {
97		assert!(len <= N);
98
99		Self {
100			buf,
101			len,
102		}
103	}
104
105	/// construct an array from an initialized array.
106	/// 
107	/// ## examples
108	/// 
109	/// ```
110	/// # use nyarray::array::Array;
111	/// let array = Array::<16, i32>::from_parts([1, 2, 3, 4]);
112	/// assert_eq!(array, [1, 2, 3, 4]);
113	/// ```
114	/// 
115	/// ## panics
116	/// 
117	/// this method panics if the const parameter `M` is larger than the
118	/// array capacity (const parameter `N`).
119	/// 
120	/// ```should_panic
121	/// # use nyarray::array::Array;
122	/// // note the input array is larger than the array capacity
123	/// let array = Array::<4, i32>::from_parts([1, 2, 3, 4, 5, 6]);
124	/// // this panics!
125	/// ```
126	#[inline]
127	pub const fn from_parts<const M: usize>(buf: [T; M]) -> Self {
128		assert!(M <= N);
129
130		let buf = core::mem::ManuallyDrop::new(buf);
131
132		let mut new_buf = [const { core::mem::MaybeUninit::uninit() }; N];
133
134		let buf_ptr = &buf as *const ManuallyDrop<[T; M]> as *const T;
135		let new_ptr = new_buf.as_mut_ptr();
136
137		unsafe {
138			core::ptr::copy_nonoverlapping(buf_ptr, new_ptr as *mut T, M);
139
140			Self::from_parts_len(new_buf, M)
141		}
142	}
143
144	/// construct an array from a raw pointer.
145	/// 
146	/// ## safety
147	/// 
148	/// - `ptr` must point to memory valid for reads of `len` elements.
149	/// - `ptr` must be aligned.
150	/// 
151	/// ## examples
152	/// 
153	/// ```
154	/// # use nyarray::array::Array;
155	/// # use std::vec;
156	/// let mut vec = vec![1, 2, 3];
157	/// let array;
158	/// 
159	/// unsafe {
160	///     let ptr = vec.as_ptr();
161	///     let len = vec.len();
162	///     vec.set_len(0);
163	///     array = Array::<4, _>::from_raw_parts(ptr, len);
164	/// }
165	/// 
166	/// assert_eq!(array, [1, 2, 3]);
167	/// ``` 
168	#[inline]
169	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
170	pub const unsafe fn from_raw_parts(ptr: *const T, len: usize) -> Self {
171		let mut new_buf = [const { core::mem::MaybeUninit::uninit() }; N];
172
173		let new_ptr = new_buf.as_mut_ptr();
174
175		unsafe {
176			core::ptr::copy_nonoverlapping(ptr, new_ptr as *mut T, len);
177
178			Self::from_parts_len(new_buf, len)
179		}
180	}
181
182	/// deconstruct an array.
183	/// 
184	/// note that, let `ret` be the output, `ret.0[0..ret.1]` is valid memory. if
185	/// `T` is `Drop`, then forgetting to drop this will leak memory.
186	/// 
187	/// the easiest way to correctly drop this is to reconstruct the array with [`Self::from_parts_len()`].
188	/// 
189	/// ## examples
190	/// 
191	/// ```
192	/// # use nyarray::array;
193	/// # use nyarray::array::Array;
194	/// let array = array![1, 2, 3 => 3];
195	/// 
196	/// let (buf, len) = array.into_parts_len();
197	/// 
198	/// // do whatever to `buf`
199	/// 
200	/// let array = unsafe { Array::from_parts_len(buf, len) };
201	/// ```
202	#[inline]
203	pub const fn into_parts_len(self) -> ([core::mem::MaybeUninit<T>; N], usize) {
204		let this = core::mem::ManuallyDrop::new(self);
205		let this_ptr = &this as *const core::mem::ManuallyDrop<Self> as *const Self;
206		let buf;
207		let len;
208		unsafe {
209			buf = core::ptr::read(&(*this_ptr).buf);
210			len = (*this_ptr).len;
211		};
212		(buf, len)
213	}
214
215	/// returns the total number of elements the array can hold.
216	/// this function always returns the const `N` parameter of this array.
217	/// 
218	/// ## examples
219	/// 
220	/// ```
221	/// # use nyarray::array;
222	/// let array = array![1, 2, 3 => 16];
223	/// assert_eq!(array.capacity(), 16);
224	/// ```
225	#[inline]
226	pub const fn capacity(&self) -> usize {
227		N
228	}
229
230	/// returns the total number of elements inside the array.
231	/// 
232	/// ## examples
233	/// 
234	/// ```
235	/// # use nyarray::array;
236	/// let array = array![1, 2, 3 => 16];
237	/// assert_eq!(array.len(), 3);
238	/// ```
239	#[inline]
240	pub const fn len(&self) -> usize {
241		self.len
242	}
243
244	/// set the length of the array to `new_len`.
245	/// 
246	/// ## safety
247	/// 
248	/// this function should be used with care, as setting `new_len` to incorrect values
249	/// can easily expose safe code to uninitialized memory.
250	/// 
251	/// - `new_len` lesser or equal to [`Self::capacity()`]
252	/// - all elements `0..new_len` must be initialized.
253	/// 
254	/// consider using other safe functions, like [`Self::clear()`] or [`Self::extend()`].
255	/// 
256	/// ## examples
257	/// 
258	/// ```
259	/// # use nyarray::array;
260	/// # use nyarray::array::Array;
261	/// unsafe fn fill(input_ptr: *const u32, input_len: usize) -> Array<16, u32> {
262	///     // it is UB to copy more than the Array capacity (16)
263	///     assert!(input_len <= 16);
264	///     let mut array = array![];
265	///     let array_ptr = array.as_mut_ptr();
266	///     unsafe {
267	///         core::ptr::copy(input_ptr, array_ptr, input_len);
268	///         // set_len *after* copying input
269	///         array.set_len(input_len);
270	///     }
271	///     array
272	/// }
273	/// ```
274	#[inline]
275	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
276	pub const unsafe fn set_len(&mut self, new_len: usize) {
277		self.len = new_len;
278	}
279
280	/// returns `true` if the array has zero elements, `false` otherwise.
281	/// 
282	/// ## examples
283	/// 
284	/// ```
285	/// # use nyarray::array;
286	/// # use nyarray::array::Array;
287	/// let array: Array<_, ()> = array![=> 4];
288	/// assert!(array.is_empty());
289	/// ```
290	#[inline]
291	pub const fn is_empty(&self) -> bool {
292		self.len() == 0
293	}
294
295	/// returns a slice containing the array.
296	/// 
297	/// ## examples
298	/// 
299	/// ```
300	/// # use nyarray::array;
301	/// # use nyarray::array::Array;
302	/// let array: Array<_, u8> = array![=> 4];
303	/// let slice: &[u8] = array.as_slice();
304	/// // let slice: &[u8] = &array[..]; // works the same
305	/// 
306	/// let string = str::from_utf8(slice);
307	/// ```
308	#[inline]
309	pub const fn as_slice(&self) -> &[T] {
310		let ptr = &self.buf as *const core::mem::MaybeUninit<T> as *const T;
311		unsafe {
312			// safety: all elements before `len` should always be initialized
313			core::slice::from_raw_parts(ptr, self.len)
314		}
315	}
316
317	/// returns a mutable slice containing the array.
318	/// 
319	/// ## examples
320	/// 
321	/// ```
322	/// # use nyarray::array;
323	/// # use nyarray::array::Array;
324	/// let mut array: Array<_, u8> = array![=> 4];
325	/// let mut slice: &mut [u8] = array.as_mut_slice();
326	/// // let mut slice: &mut [u8] = &mut array[..]; // works the same
327	/// 
328	/// let string = str::from_utf8_mut(slice);
329	/// ```
330	#[inline]
331	pub const fn as_mut_slice(&mut self) -> &mut [T] {
332		let ptr = &mut self.buf as *mut core::mem::MaybeUninit<T> as *mut T;
333		unsafe {
334			// safety: all elements before `len` should always be initialized
335			core::slice::from_raw_parts_mut(ptr, self.len)
336		}
337	}
338
339	/// returns a raw pointer to the internal buffer.
340	/// 
341	/// this pointer is valid so long as this array is valid. if the array is
342	/// dropped, or even moved, the pointer is immediately invalid.
343	#[inline]
344	pub const fn as_ptr(&self) -> *const T {
345		self.buf.as_ptr() as *const T
346	}
347
348	/// returns a mutable raw pointer to the internal buffer.
349	/// 
350	/// this pointer is valid so long as this array is valid. if the array is
351	/// dropped, or even moved, the pointer is immediately invalid.
352	#[inline]
353	pub const fn as_mut_ptr(&mut self) -> *mut T {
354		self.buf.as_mut_ptr() as *mut T
355	}
356
357	/// removes all elements from the array.
358	/// 
359	/// ## examples
360	/// 
361	/// ```
362	/// # use nyarray::array;
363	/// let mut array = array![1, 2, 3 => 4];
364	/// array.clear();
365	/// assert!(array.is_empty());
366	/// ```
367	#[inline]
368	pub fn clear(&mut self) {
369		unsafe {
370			let elements = self.as_mut_slice() as *mut [T];
371			core::ptr::drop_in_place(elements);
372			self.set_len(0);
373		}
374	}
375
376	/// add an element to the end of the array.
377	/// 
378	/// ## examples
379	/// 
380	/// ```
381	/// # use nyarray::array;
382	/// let mut array = array![=> 4];
383	/// array.push(1);
384	/// array.push(2);
385	/// array.push(3);
386	/// assert_eq!(array, [1, 2, 3]);
387	/// ```
388	/// 
389	/// ## panics
390	/// 
391	/// this method panics if there isn't enough space for another element.
392	/// for a non-panicking version, see [`Self::push_checked()`].
393	/// 
394	/// ```should_panic
395	/// # use nyarray::array;
396	/// let mut array = array![=> 4];
397	/// array.push(1);
398	/// array.push(2);
399	/// array.push(3);
400	/// array.push(4);
401	/// array.push(5); // panics
402	/// ```
403	#[inline]
404	pub fn push(&mut self, value: T) {
405		if self.push_checked(value).is_err() {
406			panic!("push exceeds capacity");
407		}
408	}
409
410	/// add an element to the end of the array. returns `Err(T)` if
411	/// there is not enough capacity.
412	/// 
413	/// ## examples
414	/// 
415	/// ```
416	/// # fn main() -> Result<(), i32> {
417	/// # use nyarray::array;
418	/// let mut array = array![=> 4];
419	/// array.push_checked(1)?;
420	/// array.push_checked(2)?;
421	/// array.push_checked(3)?;
422	/// assert_eq!(array, [1, 2, 3]);
423	/// # Ok(())
424	/// # }
425	/// ```
426	#[inline]
427	pub const fn push_checked(&mut self, value: T) -> Result<(), T> {
428		if self.len() == self.capacity() {
429			Err(value)
430		} else {
431			unsafe {
432				// safety: just confirmed there is enough space for another element
433				self.push_unchecked(value);
434			}
435			Ok(())
436		}
437	}
438
439	/// add an element to the end of the array.
440	/// 
441	/// this is the unsafe version of this method. see [`Self::push()`] or
442	/// [`Self::push_checked()`] for safe versions of this.
443	/// 
444	/// ## safety
445	/// 
446	/// there must be enough capacity in the array for at least one more element
447	/// before calling this method. ie; [`Self::len()`] `<` [`Self::capacity()`].
448	/// 
449	/// ## examples
450	/// 
451	/// ```
452	/// # fn main() -> Result<(), i32> {
453	/// # use nyarray::array;
454	/// let mut array = array![=> 4];
455	/// unsafe {
456	///     // safety: array has capacity of 4 elements.
457	///     array.push_unchecked(1);
458	///     array.push_unchecked(2);
459	///     array.push_unchecked(3);
460	///     array.push_unchecked(4);
461	///    // array.push_unchecked(5); // UB
462	/// }
463	/// assert_eq!(array, [1, 2, 3, 4]);
464	/// # Ok(())
465	/// # }
466	/// ```
467	#[inline]
468	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
469	pub const unsafe fn push_unchecked(&mut self, value: T) {
470		unsafe {
471			let len = self.len();
472
473			// safety: caller ensures there is enough space for another element
474			let ptr = self.as_mut_ptr().add(len);
475
476			core::ptr::write(ptr, value);
477
478			// set length to accomodate for new element
479			self.set_len(len + 1);
480		}
481	}
482
483	/// remove and return an element from the end of the array.
484	/// returns `None` if the array is empty.
485	/// 
486	/// ## examples
487	/// 
488	/// ```
489	/// # use nyarray::array;
490	/// let mut array = array![1, 2, 3 => 4];
491	/// assert_eq!(array.pop(), Some(3));
492	/// assert_eq!(array.pop(), Some(2));
493	/// assert_eq!(array.pop(), Some(1));
494	/// assert_eq!(array.pop(), None);
495	/// ```
496	#[inline]
497	pub const fn pop(&mut self) -> Option<T> {
498		if self.is_empty() {
499			None
500		} else {
501			unsafe {
502				// safety: just confirmed there is an element in the array
503				Some(self.pop_unchecked())
504			}
505		}
506	}
507
508	/// remove and return an element from the end of the array.
509	/// 
510	/// this is the unsafe version of this method. see [`Self::pop()`] for
511	/// the safe version.
512	/// 
513	/// ## safety
514	/// 
515	/// there must be at least one element in the array prior to calling
516	/// this method. ie; [`Self::len()`] `!= 0`
517	/// 
518	/// ## examples
519	/// 
520	/// ```
521	/// # use nyarray::array;
522	/// let mut array = array![1, 2, 3 => 4];
523	/// 
524	/// unsafe {
525	///     // safety: array has 3 elements
526	///     assert_eq!(array.pop_unchecked(), 3);
527	///     assert_eq!(array.pop_unchecked(), 2);
528	///     assert_eq!(array.pop_unchecked(), 1);
529	///     // array.pop_unchecked() // UB
530	/// }
531	/// 
532	/// assert!(array.is_empty());
533	/// ```
534	#[inline]
535	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
536	pub const unsafe fn pop_unchecked(&mut self) -> T {
537		unsafe {
538			// safety: caller ensures there is at least one element.
539
540			// underflows if no elements
541			let len = self.len() - 1;
542
543			// first set len to new len
544			self.set_len(len);
545
546			core::ptr::read(self.as_ptr().add(len))
547		}
548	}
549
550	/// insert an element into any index of the array, shifting
551	/// all elements after towards the end.
552	/// 
553	/// ## examples
554	/// 
555	/// ```
556	/// # use nyarray::array;
557	/// let mut array = array![1, 2, 3 => 6];
558	/// 
559	/// array.insert(2, 10);
560	/// assert_eq!(array, [1, 2, 10, 3]);
561	/// 
562	/// array.insert(0, 20);
563	/// assert_eq!(array, [20, 1, 2, 10, 3]);
564	/// 
565	/// array.insert(5, 30);
566	/// assert_eq!(array, [20, 1, 2, 10, 3, 30]);
567	/// ```
568	///  
569	/// ## panics
570	/// 
571	/// this method panics if there isn't enough space for another element,
572	/// or if `index` is not `0..self.len()`.
573	/// for a non-panicking version, see [`Self::insert_checked()`].
574	/// 
575	/// ```should_panic
576	/// # use nyarray::array;
577	/// let mut array = array![1, 2, 3 => 4];
578	/// array.insert(0, 4); // okay
579	/// array.insert(0, 5); // panics
580	/// ```
581	#[inline]
582	pub fn insert(&mut self, index: usize, element: T) {
583		if self.insert_checked(index, element).is_err() {
584			if index > self.len() {
585				panic!("index out of bounds");
586			} else {
587				panic!("insert exceeds capacity");
588			}
589		}
590	}
591
592	/// insert an element into any index of the array, shifting
593	/// all elements after towards the end. returns Err(T) if there
594	/// is not enough capacity, or if `index` is not `0..=self.len()`.
595	/// 
596	/// ## examples
597	/// 
598	/// ```
599	/// # fn main() -> Result<(), i32> {
600	/// # use nyarray::array;
601	/// let mut array = array![1, 2, 3 => 6];
602	/// 
603	/// array.insert_checked(2, 10)?;
604	/// assert_eq!(array, [1, 2, 10, 3]);
605	/// 
606	/// array.insert_checked(0, 20)?;
607	/// assert_eq!(array, [20, 1, 2, 10, 3]);
608	/// 
609	/// array.insert_checked(5, 30)?;
610	/// assert_eq!(array, [20, 1, 2, 10, 3, 30]);
611	/// # Ok(())
612	/// # }
613	/// ```
614	#[inline]
615	pub const fn insert_checked(&mut self, index: usize, element: T) -> Result<(), T> {
616		if index > self.len() {
617			return Err(element);
618		}
619
620		if self.len() + 1 > self.capacity() {
621			return Err(element);
622		}
623
624		unsafe {
625			// safety: just confirmed index is in bounds and there is enough capacity
626			self.insert_unchecked(index, element);
627		}
628
629		Ok(())
630	}
631
632	/// insert an element into any index of the array, shifting
633	/// all elements after towards the end.
634	/// 
635	/// this is the unsafe version of this method. see [`Self::insert_checked()`] or
636	/// [`Self::insert()`] for safe versions.
637	/// 
638	/// ## safety
639	/// 
640	/// - there must be enough capacity in the array for at least one more element
641	///   prior to calling this method. ie; [`Self::len()`] `<` [`Self::capacity()`].
642	/// - `index` `<=` [`Self::len()`]
643	/// 
644	/// ## examples
645	/// 
646	/// ```
647	/// # use nyarray::array;
648	/// let mut array = array![=> 4];
649	/// 
650	/// unsafe {
651	///     // safety: array has capacity of 4 elements.
652	///     array.insert_unchecked(0, 1);
653	///     array.insert_unchecked(0, 2);
654	///     array.insert_unchecked(0, 3);
655	///     array.insert_unchecked(0, 4);
656	///     // array.insert_unchecked(0, 5); // UB
657	/// }
658	/// 
659	/// assert_eq!(array, [4, 3, 2, 1]);
660	/// ```
661	#[inline]
662	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
663	pub const unsafe fn insert_unchecked(&mut self, index: usize, element: T) {
664		unsafe {
665			let len = self.len();
666
667			let ptr = self.as_mut_ptr().add(index);
668
669			if index != len {
670				core::ptr::copy(ptr, ptr.add(1), len - index);
671			}
672
673			core::ptr::write(ptr, element);
674
675			self.set_len(len + 1);
676		}
677	}
678
679	/// insert an element into any index of the array, moving the element
680	/// that was previously there to the end.
681	/// 
682	/// ## examples
683	/// 
684	/// ```
685	/// # use nyarray::array;
686	/// let mut array = array![1, 2, 3 => 6];
687	/// 
688	/// array.swap_insert(2, 10);
689	/// assert_eq!(array, [1, 2, 10, 3]);
690	/// 
691	/// array.swap_insert(0, 20);
692	/// assert_eq!(array, [20, 2, 10, 3, 1]);
693	/// 
694	/// array.swap_insert(5, 30);
695	/// assert_eq!(array, [20, 2, 10, 3, 1, 30]);
696	/// ```
697	///  
698	/// ## panics
699	/// 
700	/// this method panics if there isn't enough space for another element,
701	/// or if `index` is not `0..=self.len()`.
702	/// for a non-panicking version, see [`Self::swap_insert_checked()`].
703	/// 
704	/// ```should_panic
705	/// # use nyarray::array;
706	/// let mut array = array![1, 2, 3 => 4];
707	/// array.swap_insert(0, 4); // okay
708	/// array.swap_insert(0, 5); // panics
709	/// ```
710	#[inline]
711	pub fn swap_insert(&mut self, index: usize, element: T) {
712		if self.swap_insert_checked(index, element).is_err() {
713			if index > self.len() {
714				panic!("index out of bounds");
715			} else {
716				panic!("insert exceeds capacity");
717			}
718		}
719	}
720
721	/// insert an element into any index of the array, moving the element
722	/// that was previously there to the end. returns Err(T) if there
723	/// is not enough capacity, or if `index` is not `0..=self.len()`.
724	/// 
725	/// ## examples
726	/// 
727	/// ```
728	/// # fn main() -> Result<(), i32> {
729	/// # use nyarray::array;
730	/// let mut array = array![1, 2, 3 => 6];
731	/// 
732	/// array.swap_insert_checked(2, 10)?;
733	/// assert_eq!(array, [1, 2, 10, 3]);
734	/// 
735	/// array.swap_insert_checked(0, 20)?;
736	/// assert_eq!(array, [20, 2, 10, 3, 1]);
737	/// 
738	/// array.swap_insert_checked(5, 30)?;
739	/// assert_eq!(array, [20, 2, 10, 3, 1, 30]);
740	/// # Ok(())
741	/// # }
742	/// ```
743	#[inline]
744	pub const fn swap_insert_checked(&mut self, index: usize, element: T) -> Result<(), T> {
745		if index > self.len() {
746			return Err(element);
747		}
748
749		if self.len() + 1 > self.capacity() {
750			return Err(element);
751		}
752
753		unsafe {
754			// safety: just confirmed index is in bounds and there is enough capacity
755			self.swap_insert_unchecked(index, element);
756		}
757
758		Ok(())
759	}
760
761	/// insert an element into any index of the array, moving the element
762	/// that was previously there to the end.
763	/// 
764	/// this is the unsafe version of this method. see [`Self::swap_insert_checked()`]
765	/// or [`Self::swap_insert()`] for safe versions.
766	/// 
767	/// ## safety
768	/// 
769	/// - there must be enough capacity in the array for at least one more element
770	///   prior to calling this method. ie; [`Self::len()`] `<` [`Self::capacity()`].
771	/// - `index` `<=` [`Self::len()`]
772	/// 
773	/// ## examples
774	/// 
775	/// ```
776	/// # use nyarray::array;
777	/// let mut array = array![=> 4];
778	/// 
779	/// unsafe {
780	///     // safety: array has a capacity of 4
781	///     array.swap_insert_unchecked(0, 1);
782	///     array.swap_insert_unchecked(0, 2);
783	///     array.swap_insert_unchecked(0, 3);
784	///     array.swap_insert_unchecked(0, 4);
785	///     // array.swap_insert_unchecked(0, 5); // UB
786	/// }
787	/// 
788	/// assert_eq!(array, [4, 1, 2, 3])
789	/// ```
790	#[inline]
791	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
792	pub const unsafe fn swap_insert_unchecked(&mut self, index: usize, element: T) {
793		unsafe {
794			let len = self.len();
795
796			let ptr = self.as_mut_ptr();
797
798			// safety: caller ensures `index` is in bounds and there is enough
799			// space for another element.
800			let old_ptr = ptr.add(index);
801			let new_ptr = ptr.add(len);
802
803			core::ptr::write(new_ptr, element);
804			core::ptr::swap(old_ptr, new_ptr);
805			
806			self.set_len(len + 1);
807		}
808	}
809
810	/// remove and return an element out of any index of the array,
811	/// shifting all elements after towards the start.
812	/// 
813	/// ## examples
814	/// 
815	/// ```
816	/// # use nyarray::array;
817	/// let mut array = array![1, 2, 3, 4, 5, 6 => 6];
818	/// 
819	/// assert_eq!(array.remove(0), 1);
820	/// assert_eq!(array, [2, 3, 4, 5, 6]);
821	/// 
822	/// assert_eq!(array.remove(2), 4);
823	/// assert_eq!(array, [2, 3, 5, 6]);
824	/// 
825	/// assert_eq!(array.remove(3), 6);
826	/// assert_eq!(array, [2, 3, 5]);
827	/// ```
828	/// 
829	/// ## panics
830	/// 
831	/// this method panics if `index` is not `0..self.len()`.
832	/// for a non-panicking version, see [`Self::remove_checked()`].
833	/// 
834	/// ```should_panic
835	/// # use nyarray::array;
836	/// let mut array = array![1, 2, 3, 4 => 4];
837	/// array.remove(4); // panics
838	/// ```
839	#[inline]
840	pub fn remove(&mut self, index: usize) -> T {
841		if let Some(x) = self.remove_checked(index) {
842			x
843		} else {
844			panic!("index out of bounds");
845		}
846	}
847
848	/// remove and return an element out of any index of the array,
849	/// shifting all elements after towards the start. returns `None`
850	/// if `index` is not `0..self.len()`.
851	/// 
852	/// ## examples
853	/// 
854	/// ```
855	/// # use nyarray::array;
856	/// let mut array = array![1, 2, 3, 4, 5, 6 => 6];
857	/// 
858	/// assert_eq!(array.remove_checked(0), Some(1));
859	/// assert_eq!(array, [2, 3, 4, 5, 6]);
860	/// 
861	/// assert_eq!(array.remove_checked(2), Some(4));
862	/// assert_eq!(array, [2, 3, 5, 6]);
863	/// 
864	/// assert_eq!(array.remove_checked(3), Some(6));
865	/// assert_eq!(array, [2, 3, 5]);
866	/// 
867	/// assert_eq!(array.remove_checked(3), None);
868	/// assert_eq!(array, [2, 3, 5]);
869	/// ```
870	#[inline]
871	pub const fn remove_checked(&mut self, index: usize) -> Option<T> {
872		if index >= self.len() {
873			return None;
874		}
875
876		unsafe {
877			Some(self.remove_unchecked(index))
878		}
879	}
880
881	/// remove and return an element out of any index of the array,
882	/// shifting all elements after towards the start.
883	/// 
884	/// this is the unsafe version of this method. see [`Self::remove_checked()`]
885	/// or [`Self::remove()`] for safe versions.
886	/// 
887	/// ## safety
888	/// 
889	/// - there must be at least one element in the array prior to calling
890	///   this method. ie; [`Self::len()`] `!= 0`
891	/// - `index` `<` [`Self::len()`]
892	/// 
893	/// ## examples
894	/// 
895	/// ```
896	/// # use nyarray::array;
897	/// let mut array = array![1, 2, 3, 4 => 4];
898	/// 
899	/// unsafe {
900	///     // safety: array has 4 elements.
901	///     assert_eq!(array.remove_unchecked(0), 1);
902	///     assert_eq!(array.remove_unchecked(0), 2);
903	///     assert_eq!(array.remove_unchecked(0), 3);
904	///     assert_eq!(array.remove_unchecked(0), 4);
905	///     // array.remove_unchecked(0) // UB
906	/// }
907	/// 
908	/// assert!(array.is_empty());
909	/// ```
910	#[inline]
911	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
912	pub const unsafe fn remove_unchecked(&mut self, index: usize) -> T {		
913		unsafe {
914			let len = self.len();
915
916			// safety: caller ensures index is in bounds and there is at least one element
917			let ptr = self.as_mut_ptr().add(index);
918
919			let old = core::ptr::read(ptr);
920
921			core::ptr::copy(ptr.add(1), ptr, len - index - 1);
922
923			self.set_len(len - 1);
924
925			old
926		}
927	}
928
929	/// remove and return an element from any index of the array,
930	/// moving the element that was previously at the end to there.
931	/// 
932	/// ## examples
933	/// 
934	/// ```
935	/// # use nyarray::array;
936	/// let mut array = array![1, 2, 3, 4, 5, 6 => 6];
937	/// 
938	/// assert_eq!(array.swap_remove(0), 1);
939	/// assert_eq!(array, [6, 2, 3, 4, 5]);
940	/// 
941	/// assert_eq!(array.swap_remove(2), 3);
942	/// assert_eq!(array, [6, 2, 5, 4]);
943	/// 
944	/// assert_eq!(array.swap_remove(3), 4);
945	/// assert_eq!(array, [6, 2, 5]);
946	/// ```
947	/// 
948	/// ## panics
949	/// 
950	/// this method panics if `index` is not `0..=self.len()`.
951	/// for a non-panicking version, see [`Self::swap_remove_checked()`].
952	/// 
953	/// ```should_panic
954	/// # use nyarray::array;
955	/// let mut array = array![1, 2, 3, 4 => 4];
956	/// array.swap_remove(4); // panics
957	/// ```
958	#[inline]
959	pub fn swap_remove(&mut self, index: usize) -> T {
960		if let Some(x) = self.swap_remove_checked(index) {
961			x
962		} else {
963			panic!("index out of bounds");
964		}
965	}
966
967	/// remove and return an element from any index of the array,
968	/// moving the element that was previously at the end to there.
969	/// returns `None` if `index` is not `0..self.len()`.
970	/// 
971	/// ## examples
972	/// 
973	/// ```
974	/// # use nyarray::array;
975	/// let mut array = array![1, 2, 3, 4, 5, 6 => 6];
976	/// 
977	/// assert_eq!(array.swap_remove_checked(0), Some(1));
978	/// assert_eq!(array, [6, 2, 3, 4, 5]);
979	/// 
980	/// assert_eq!(array.swap_remove_checked(2), Some(3));
981	/// assert_eq!(array, [6, 2, 5, 4]);
982	/// 
983	/// assert_eq!(array.swap_remove_checked(3), Some(4));
984	/// assert_eq!(array, [6, 2, 5]);
985	/// 
986	/// assert_eq!(array.swap_remove_checked(3), None);
987	/// assert_eq!(array, [6, 2, 5]);
988	/// ```
989	#[inline]
990	pub const fn swap_remove_checked(&mut self, index: usize) -> Option<T> {
991		let len = self.len();
992		if index >= len {
993			return None;
994		}
995
996		unsafe {
997			Some(self.swap_remove_unchecked(index))
998		}
999	}
1000
1001	/// remove and return an element from any index of the array,
1002	/// moving the element that was previously at the end to there.
1003	/// returns `None` if `index` is not `0..self.len()`.
1004	/// 
1005	/// this is the unsafe version of this method. see [`Self::swap_remove_checked()`]
1006	/// or [`Self::swap_remove()`] for safe versions.
1007	/// 
1008	/// ## safety
1009	/// 
1010	/// - there must be at least one element in the array prior to calling
1011	///   this method. ie; [`Self::len()`] `!= 0`
1012	/// - `index` `<` [`Self::len()`]
1013	/// 
1014	/// ## examples
1015	/// 
1016	/// ```
1017	/// # use nyarray::array;
1018	/// let mut array = array![1, 2, 3, 4 => 4];
1019	/// 
1020	/// unsafe {
1021	///     // safety: array has 4 elements.
1022	///     assert_eq!(array.swap_remove_unchecked(0), 1);
1023	///     assert_eq!(array.swap_remove_unchecked(0), 4);
1024	///     assert_eq!(array.swap_remove_unchecked(0), 3);
1025	///     assert_eq!(array.swap_remove_unchecked(0), 2);
1026	///     // array.swap_remove_unchecked(0) // UB
1027	/// }
1028	/// 
1029	/// assert!(array.is_empty());
1030	/// ```
1031	#[inline]
1032	#[expect(clippy::missing_safety_doc, reason = "there is a safety doc, not sure why the lint still generates")]
1033	pub const unsafe fn swap_remove_unchecked(&mut self, index: usize) -> T {
1034		unsafe {
1035			let len = self.len();
1036
1037			let ptr = self.as_mut_ptr();
1038			
1039			// safety: caller ensures index is in bounds and there is at least one element
1040			let old = core::ptr::read(ptr.add(index));
1041			
1042			core::ptr::copy(ptr.add(len - 1), ptr.add(index), 1);
1043			
1044			self.set_len(len - 1);
1045			
1046			old
1047		}
1048	}
1049}
1050
1051impl<const N: usize, T> Drop for Array<N, T> {
1052	fn drop(&mut self) {
1053		self.clear();
1054	}
1055}
1056
1057impl<const N: usize, T> Default for Array<N, T> {
1058	fn default() -> Self {
1059		Self::new()
1060	}
1061}
1062
1063impl<const N: usize, T: Clone> Clone for Array<N, T> {
1064	fn clone(&self) -> Self {
1065		self.iter().cloned().collect()
1066	}
1067}
1068
1069impl<const N: usize, T> AsRef<[T]> for Array<N, T> {
1070	fn as_ref(&self) -> &[T] {
1071		self.as_slice()
1072	}
1073}
1074
1075impl<const N: usize, T> AsMut<[T]> for Array<N, T> {
1076	fn as_mut(&mut self) -> &mut [T] {
1077		self.as_mut_slice()
1078	}
1079}
1080
1081impl<const N: usize, T> core::borrow::Borrow<[T]> for Array<N, T> {
1082	fn borrow(&self) -> &[T] {
1083		self.as_slice()
1084	}
1085}
1086
1087impl<const N: usize, T> core::borrow::BorrowMut<[T]> for Array<N, T> {
1088	fn borrow_mut(&mut self) -> &mut [T] {
1089		self.as_mut_slice()
1090	}
1091}
1092
1093impl<const N: usize, T> core::ops::Deref for Array<N, T> {
1094	type Target = [T];
1095	fn deref(&self) -> &Self::Target {
1096		self.as_slice()
1097	}
1098}
1099
1100impl<const N: usize, T> core::ops::DerefMut for Array<N, T> {
1101	fn deref_mut(&mut self) -> &mut Self::Target {
1102		self.as_mut_slice()
1103	}
1104}
1105
1106impl<const N: usize, T, I: core::slice::SliceIndex<[T]>> core::ops::Index<I> for Array<N, T> {
1107	type Output = I::Output;
1108	fn index(&self, index: I) -> &Self::Output {
1109		core::ops::Index::index(self.as_slice(), index)
1110	}
1111}
1112
1113impl<const N: usize, T, I: core::slice::SliceIndex<[T]>> core::ops::IndexMut<I> for Array<N, T> {
1114	fn index_mut(&mut self, index: I) -> &mut Self::Output {
1115		core::ops::IndexMut::index_mut(self.as_mut_slice(), index)
1116	}
1117}
1118
1119impl<const N: usize, T> Extend<T> for Array<N, T> {
1120	fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1121		for i in iter {
1122			if self.push_checked(i).is_err() {
1123				break;
1124			}
1125		}
1126	}
1127}
1128
1129impl<'a, const N: usize, T: Copy> Extend<&'a T> for Array<N, T> {
1130	fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
1131		for i in iter {
1132			if self.push_checked(*i).is_err() {
1133				break;
1134			}
1135		}
1136	}
1137}
1138
1139
1140#[doc(hidden)]
1141pub fn from_elem<const N: usize, T: Clone>(elem: T, n: usize) -> Array<N, T> {
1142	let mut array = Array::new();
1143	for _ in 0..n {
1144		array.push(elem.clone());
1145	}
1146	array
1147}
1148
1149
1150/// iterator for [`Array`].
1151pub struct IntoIter<const N: usize, T> {
1152	inner: [core::mem::MaybeUninit<T>; N],
1153	cur: usize,
1154	end: usize,
1155}
1156
1157impl<const N: usize, T> Drop for IntoIter<N, T> {
1158	fn drop(&mut self) {
1159		while self.cur != self.end {
1160			unsafe {
1161				self.inner.get_unchecked_mut(self.cur).assume_init_drop();
1162				self.cur += 1;
1163			}
1164		}
1165	}
1166}
1167
1168impl<const N: usize, T> Iterator for IntoIter<N, T> {
1169	type Item = T;
1170
1171	fn next(&mut self) -> Option<Self::Item> {
1172		if self.cur == self.end {
1173			return None;
1174		}
1175		unsafe {
1176			let out = self.inner.get_unchecked(self.cur).assume_init_read();
1177			self.cur += 1;
1178			Some(out)
1179		}
1180	}
1181}
1182
1183impl<const N: usize, T> DoubleEndedIterator for IntoIter<N, T> {
1184	fn next_back(&mut self) -> Option<Self::Item> {
1185		if self.cur == self.end {
1186			return None;
1187		}
1188		unsafe {
1189			self.end -= 1;
1190			Some(self.inner.get_unchecked(self.end).assume_init_read())
1191		}
1192	}
1193}
1194
1195impl<const N: usize, T> IntoIterator for Array<N, T> {
1196	type IntoIter = IntoIter<N, T>;
1197	type Item = T;
1198	
1199	fn into_iter(self) -> Self::IntoIter {
1200		let (buf, len) = self.into_parts_len();
1201		IntoIter {
1202			inner: buf,
1203			cur: 0,
1204			end: len,
1205		}
1206	}
1207}
1208
1209impl<'a, const N: usize, T> IntoIterator for &'a Array<N, T> {
1210	type IntoIter = core::slice::Iter<'a, T>;
1211	type Item = &'a T;
1212
1213	fn into_iter(self) -> Self::IntoIter {
1214		self.as_slice().iter()
1215	}
1216}
1217
1218impl<'a, const N: usize, T> IntoIterator for &'a mut Array<N, T> {
1219	type IntoIter = core::slice::IterMut<'a, T>;
1220	type Item = &'a mut T;
1221
1222	fn into_iter(self) -> Self::IntoIter {
1223		self.as_mut_slice().iter_mut()
1224	}
1225}
1226
1227impl<const N: usize, T> FromIterator<T> for Array<N, T> {
1228	fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1229		let mut out = Self::new();
1230		out.extend(iter);
1231		out
1232	}
1233}
1234
1235
1236impl<const N: usize, T: PartialOrd> PartialOrd for Array<N, T> {
1237	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1238		PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
1239	}
1240}
1241
1242impl<const N: usize, T: Eq> Eq for Array<N, T> {}
1243
1244impl<const N: usize, T: Ord> Ord for Array<N, T> {
1245	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1246		Ord::cmp(self.as_slice(), other.as_slice())
1247	}
1248}
1249
1250impl<const N: usize, const M: usize, T: PartialEq> PartialEq<Array<M, T>> for Array<N, T> {
1251	fn eq(&self, other: &Array<M, T>) -> bool {
1252		PartialEq::eq(self.as_slice(), other.as_slice())
1253	}
1254}
1255
1256impl<const N: usize, T: PartialEq> PartialEq<&[T]> for Array<N, T> {
1257	fn eq(&self, other: &&[T]) -> bool {
1258		PartialEq::eq(self.as_slice(), *other)
1259	}
1260}
1261
1262impl<const N: usize, T: PartialEq> PartialEq<&mut [T]> for Array<N, T> {
1263	fn eq(&self, other: &&mut [T]) -> bool {
1264		PartialEq::eq(self.as_slice(), *other)
1265	}
1266}
1267
1268impl<const N: usize, const M: usize, T: PartialEq> PartialEq<[T; M]> for Array<N, T> {
1269	fn eq(&self, other: &[T; M]) -> bool {
1270		PartialEq::eq(self.as_slice(), other.as_slice())
1271	}
1272}
1273
1274impl<const N: usize, const M: usize, T: PartialEq> PartialEq<&[T; M]> for Array<N, T> {
1275	fn eq(&self, other: &&[T; M]) -> bool {
1276		PartialEq::eq(self.as_slice(), other.as_slice())
1277	}
1278}
1279
1280impl<const N: usize, T: core::fmt::Debug> core::fmt::Debug for Array<N, T> {
1281	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1282		core::fmt::Debug::fmt(self.as_slice(), f)
1283	}
1284}
1285
1286
1287/// create an [`Array`].
1288/// 
1289/// like `vec!`, `array!` has similar syntax as Rust array expressions, with
1290/// the addition of allowing one to specify the capacity of the `Array`
1291/// by appending an `=>`:
1292/// 
1293/// ```
1294/// # use nyarray::array;
1295/// let array = array![1, 2, 3 => 6]; // capacity of 6 elements
1296/// assert_eq!(array[0], 1);
1297/// assert_eq!(array[1], 2);
1298/// assert_eq!(array[2], 3);
1299/// ```
1300#[macro_export]
1301macro_rules! array {
1302	() => {
1303		$crate::array::Array::new()
1304	};
1305	(=> $cap:literal) => {
1306		$crate::array::Array::<$cap, _>::new()
1307	};
1308	($elem:expr; $n:expr) => {
1309		$crate::array::from_elem($elem, $n)
1310	};
1311	($elem:expr; $n:expr => $cap:literal) => {
1312		$crate::array::from_elem::<$cap, _>($elem, $n)
1313	};
1314	($($x:expr),+ $(,)?) => {
1315		$crate::array::Array::from_parts([$($x),+])
1316	};
1317	($($x:expr),+ $(,)? => $cap:literal) => {
1318		$crate::array::Array::<$cap, _>::from_parts([$($x),+])
1319	};
1320}
1321
1322
1323#[cfg(test)]
1324mod test {
1325	extern crate std;
1326
1327	#[test]
1328	fn test_drop() {
1329		static mut NUM: u32 = 0;
1330
1331		struct Box<T> {
1332			_inner: std::boxed::Box<T>,
1333		}
1334		impl<T> Box<T> {
1335			fn new(inner: T) -> Self {
1336				Self {
1337					_inner: std::boxed::Box::new(inner),
1338				}
1339			}
1340		}
1341		impl<T> Drop for Box<T> {
1342			fn drop(&mut self) {
1343				unsafe {
1344					NUM += 1;
1345				}
1346			}
1347		}
1348
1349		let array = array![Box::new(1), Box::new(2), Box::new(3) => 4];
1350		
1351		drop(array);
1352		
1353		assert_eq!(unsafe { NUM }, 3);
1354		
1355		let array = array![Box::new(1), Box::new(2), Box::new(3) => 4];
1356		let mut iter = array.into_iter();
1357		iter.next();
1358		
1359		drop(iter);
1360
1361		assert_eq!(unsafe { NUM }, 6);
1362	}
1363
1364	#[test]
1365	fn test_iter() {
1366		let array = array![std::boxed::Box::new(1) => 4];
1367		let _ = array.iter().cloned().collect::<crate::array::Array<4, _>>();
1368	}
1369}
1370