1#![no_std]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8#![warn(
9 clippy::arithmetic_side_effects,
10 clippy::cast_lossless,
11 clippy::cast_possible_truncation,
12 clippy::cast_possible_wrap,
13 clippy::cast_precision_loss,
14 clippy::cast_sign_loss,
15 clippy::checked_conversions,
16 clippy::from_iter_instead_of_collect,
17 clippy::missing_errors_doc,
18 clippy::mod_module_files,
19 clippy::implicit_saturating_sub,
20 clippy::panic,
21 clippy::panic_in_result_fn,
22 clippy::unwrap_used,
23 missing_docs,
24 missing_debug_implementations,
25 rust_2018_idioms,
26 trivial_casts,
27 trivial_numeric_casts,
28 unused_lifetimes,
29 unused_qualifications
30)]
31
32pub mod sizes;
110
111mod from_fn;
112mod iter;
113mod traits;
114
115#[cfg(feature = "serde")]
116mod serde;
117
118pub use crate::{iter::TryFromIteratorError, traits::*};
119pub use typenum;
120
121use core::{
122 array::TryFromSliceError,
123 borrow::{Borrow, BorrowMut},
124 cmp::Ordering,
125 fmt::{self, Debug},
126 hash::{Hash, Hasher},
127 mem::{self, ManuallyDrop, MaybeUninit},
128 ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
129 ptr,
130 slice::{self, Iter, IterMut},
131};
132use typenum::{Diff, Sum};
133
134#[cfg(feature = "bytemuck")]
135use bytemuck::{Pod, Zeroable};
136
137#[cfg(feature = "zeroize")]
138use zeroize::{Zeroize, ZeroizeOnDrop};
139
140pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
142
143#[repr(transparent)]
184pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
185
186type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
187type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
188type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
189
190impl<T, U> Array<T, U>
191where
192 U: ArraySize,
193{
194 #[inline]
196 pub fn as_slice(&self) -> &[T] {
197 self.0.as_ref()
198 }
199
200 #[inline]
202 pub fn as_mut_slice(&mut self) -> &mut [T] {
203 self.0.as_mut()
204 }
205
206 #[inline]
208 pub fn iter(&self) -> Iter<'_, T> {
209 self.as_slice().iter()
210 }
211
212 #[inline]
214 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
215 self.as_mut().iter_mut()
216 }
217
218 pub fn map<F, O>(self, f: F) -> Array<O, U>
221 where
222 F: FnMut(T) -> O,
223 {
224 self.into_iter().map(f).collect()
225 }
226
227 #[inline]
229 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
230 where
231 N: ArraySize,
232 U: Add<N>,
233 Sum<U, N>: ArraySize,
234 {
235 let mut c = Array::uninit();
236 let (left, right) = c.split_at_mut(self.len());
237 for (val, dst) in self.into_iter().zip(left) {
238 dst.write(val);
239 }
240 for (val, dst) in other.into_iter().zip(right) {
241 dst.write(val);
242 }
243 unsafe { c.assume_init() }
245 }
246
247 #[inline]
251 pub fn split<N>(self) -> SplitResult<T, U, N>
252 where
253 U: Sub<N>,
254 N: ArraySize,
255 Diff<U, N>: ArraySize,
256 {
257 unsafe {
258 let array = ManuallyDrop::new(self);
259 let head = ptr::read(array.as_ptr().cast());
260 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
261 (head, tail)
262 }
263 }
264
265 #[inline]
267 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
268 where
269 U: Sub<N>,
270 N: ArraySize,
271 Diff<U, N>: ArraySize,
272 {
273 unsafe {
274 let array_ptr = self.as_ptr();
275 let head = &*array_ptr.cast();
276 let tail = &*array_ptr.add(N::USIZE).cast();
277 (head, tail)
278 }
279 }
280
281 #[inline]
283 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
284 where
285 U: Sub<N>,
286 N: ArraySize,
287 Diff<U, N>: ArraySize,
288 {
289 unsafe {
290 let array_ptr = self.as_mut_ptr();
291 let head = &mut *array_ptr.cast();
292 let tail = &mut *array_ptr.add(N::USIZE).cast();
293 (head, tail)
294 }
295 }
296
297 #[allow(clippy::arithmetic_side_effects)]
303 #[inline]
304 pub fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
305 assert_ne!(U::USIZE, 0, "chunk size must be non-zero");
306 let chunks_len = buf.len() / U::USIZE;
310 let tail_pos = U::USIZE * chunks_len;
311 let tail_len = buf.len() - tail_pos;
312 unsafe {
313 let ptr = buf.as_ptr();
314 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
315 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
316 (chunks, tail)
317 }
318 }
319
320 #[allow(clippy::arithmetic_side_effects)]
326 #[inline]
327 pub fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
328 assert_ne!(U::USIZE, 0, "chunk size must be non-zero");
329 let chunks_len = buf.len() / U::USIZE;
333 let tail_pos = U::USIZE * chunks_len;
334 let tail_len = buf.len() - tail_pos;
335 unsafe {
336 let ptr = buf.as_mut_ptr();
337 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
338 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
339 (chunks, tail)
340 }
341 }
342
343 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
349 #[inline]
350 pub fn from_slice(slice: &[T]) -> &Self {
351 slice.try_into().expect("slice length mismatch")
352 }
353
354 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
360 #[inline]
361 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
362 slice.try_into().expect("slice length mismatch")
363 }
364
365 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
371 #[inline]
372 pub fn clone_from_slice(slice: &[T]) -> Self
373 where
374 Self: Clone,
375 {
376 slice.try_into().expect("slice length mismatch")
377 }
378}
379
380impl<T, U, const N: usize> Array<T, U>
382where
383 U: ArraySize<ArrayType<T> = [T; N]>,
384{
385 #[inline]
387 pub fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
388 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
390 }
391
392 #[inline]
394 pub fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
395 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
397 }
398
399 #[inline]
401 pub fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
402 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
404 }
405
406 #[inline]
408 pub fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
409 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
411 }
412}
413
414impl<T, U> Array<MaybeUninit<T>, U>
415where
416 U: ArraySize,
417{
418 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
420 #[allow(clippy::uninit_assumed_init)]
429 Self(unsafe { MaybeUninit::uninit().assume_init() })
430 }
431
432 #[inline]
439 pub unsafe fn assume_init(self) -> Array<T, U> {
440 unsafe {
441 mem::transmute_copy(&self)
453 }
454 }
455}
456
457impl<T, U> AsRef<Array<T, U>> for Array<T, U>
458where
459 U: ArraySize,
460{
461 #[inline]
462 fn as_ref(&self) -> &Self {
463 self
464 }
465}
466
467impl<T, U> AsRef<[T]> for Array<T, U>
468where
469 U: ArraySize,
470{
471 #[inline]
472 fn as_ref(&self) -> &[T] {
473 self.0.as_ref()
474 }
475}
476
477impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
478where
479 U: ArraySize<ArrayType<T> = [T; N]>,
480{
481 #[inline]
482 fn as_ref(&self) -> &[T; N] {
483 &self.0
484 }
485}
486
487impl<T, U, const N: usize> AsRef<Array<T, U>> for [T; N]
488where
489 U: ArraySize<ArrayType<T> = [T; N]>,
490{
491 #[inline]
492 fn as_ref(&self) -> &Array<T, U> {
493 unsafe { &*self.as_ptr().cast() }
495 }
496}
497
498impl<T, U> AsMut<[T]> for Array<T, U>
499where
500 U: ArraySize,
501{
502 #[inline]
503 fn as_mut(&mut self) -> &mut [T] {
504 self.0.as_mut()
505 }
506}
507
508impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
509where
510 U: ArraySize<ArrayType<T> = [T; N]>,
511{
512 #[inline]
513 fn as_mut(&mut self) -> &mut [T; N] {
514 &mut self.0
515 }
516}
517
518impl<T, U, const N: usize> AsMut<Array<T, U>> for [T; N]
519where
520 U: ArraySize<ArrayType<T> = [T; N]>,
521{
522 #[inline]
523 fn as_mut(&mut self) -> &mut Array<T, U> {
524 unsafe { &mut *self.as_mut_ptr().cast() }
526 }
527}
528
529impl<T, U> Borrow<[T]> for Array<T, U>
530where
531 U: ArraySize,
532{
533 #[inline]
534 fn borrow(&self) -> &[T] {
535 self.0.as_ref()
536 }
537}
538
539impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
540where
541 U: ArraySize<ArrayType<T> = [T; N]>,
542{
543 #[inline]
544 fn borrow(&self) -> &[T; N] {
545 &self.0
546 }
547}
548
549impl<T, U> BorrowMut<[T]> for Array<T, U>
550where
551 U: ArraySize,
552{
553 #[inline]
554 fn borrow_mut(&mut self) -> &mut [T] {
555 self.0.as_mut()
556 }
557}
558
559impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
560where
561 U: ArraySize<ArrayType<T> = [T; N]>,
562{
563 #[inline]
564 fn borrow_mut(&mut self) -> &mut [T; N] {
565 &mut self.0
566 }
567}
568
569impl<T, U> Clone for Array<T, U>
570where
571 T: Clone,
572 U: ArraySize,
573{
574 #[inline]
575 fn clone(&self) -> Self {
576 Self::from_fn(|n| self.0.as_ref()[n].clone())
577 }
578}
579
580impl<T, U> Copy for Array<T, U>
581where
582 T: Copy,
583 U: ArraySize,
584 U::ArrayType<T>: Copy,
585{
586}
587
588impl<T, U> Debug for Array<T, U>
589where
590 T: Debug,
591 U: ArraySize,
592{
593 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
595 }
596}
597
598impl<T, U> Default for Array<T, U>
599where
600 T: Default,
601 U: ArraySize,
602{
603 #[inline]
604 fn default() -> Self {
605 Self::from_fn(|_| Default::default())
606 }
607}
608
609impl<T, U> Deref for Array<T, U>
610where
611 U: ArraySize,
612{
613 type Target = [T];
614
615 #[inline]
616 fn deref(&self) -> &[T] {
617 self.0.as_ref()
618 }
619}
620
621impl<T, U> DerefMut for Array<T, U>
622where
623 U: ArraySize,
624{
625 #[inline]
626 fn deref_mut(&mut self) -> &mut [T] {
627 self.0.as_mut()
628 }
629}
630
631impl<T, U> Eq for Array<T, U>
632where
633 T: Eq,
634 U: ArraySize,
635{
636}
637
638impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
639where
640 U: ArraySize<ArrayType<T> = [T; N]>,
641{
642 #[inline]
643 fn from(arr: [T; N]) -> Array<T, U> {
644 Array(arr)
645 }
646}
647
648impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
649where
650 U: ArraySize<ArrayType<T> = [T; N]>,
651{
652 #[inline]
653 fn from(arr: Array<T, U>) -> [T; N] {
654 arr.0
655 }
656}
657
658impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
659where
660 U: ArraySize<ArrayType<T> = [T; N]>,
661{
662 #[inline]
663 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
664 array_ref.as_ref()
665 }
666}
667
668impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
669where
670 U: ArraySize<ArrayType<T> = [T; N]>,
671{
672 #[inline]
673 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
674 array_ref.as_ref()
675 }
676}
677
678impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
679where
680 U: ArraySize<ArrayType<T> = [T; N]>,
681{
682 #[inline]
683 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
684 array_ref.as_mut()
685 }
686}
687
688impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
689where
690 U: ArraySize<ArrayType<T> = [T; N]>,
691{
692 #[inline]
693 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
694 array_ref.as_mut()
695 }
696}
697
698impl<T, U> Hash for Array<T, U>
699where
700 T: Hash,
701 U: ArraySize,
702{
703 #[inline]
704 fn hash<H: Hasher>(&self, state: &mut H) {
705 self.0.as_ref().hash(state);
706 }
707}
708
709impl<T, I, U> Index<I> for Array<T, U>
710where
711 [T]: Index<I>,
712 U: ArraySize,
713{
714 type Output = <[T] as Index<I>>::Output;
715
716 #[inline]
717 fn index(&self, index: I) -> &Self::Output {
718 Index::index(self.as_slice(), index)
719 }
720}
721
722impl<T, I, U> IndexMut<I> for Array<T, U>
723where
724 [T]: IndexMut<I>,
725 U: ArraySize,
726{
727 #[inline]
728 fn index_mut(&mut self, index: I) -> &mut Self::Output {
729 IndexMut::index_mut(self.as_mut_slice(), index)
730 }
731}
732
733impl<T, U> PartialEq for Array<T, U>
734where
735 T: PartialEq,
736 U: ArraySize,
737{
738 #[inline]
739 fn eq(&self, other: &Self) -> bool {
740 self.0.as_ref().eq(other.0.as_ref())
741 }
742}
743
744impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
745where
746 T: PartialEq,
747 U: ArraySize<ArrayType<T> = [T; N]>,
748{
749 #[inline]
750 fn eq(&self, other: &[T; N]) -> bool {
751 self.0.eq(other)
752 }
753}
754
755impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
756where
757 T: PartialEq,
758 U: ArraySize<ArrayType<T> = [T; N]>,
759{
760 #[inline]
761 fn eq(&self, other: &Array<T, U>) -> bool {
762 self.eq(&other.0)
763 }
764}
765
766impl<T, U> PartialOrd for Array<T, U>
767where
768 T: PartialOrd,
769 U: ArraySize,
770{
771 #[inline]
772 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
773 self.0.as_ref().partial_cmp(other.0.as_ref())
774 }
775}
776
777impl<T, U> Ord for Array<T, U>
778where
779 T: Ord,
780 U: ArraySize,
781{
782 #[inline]
783 fn cmp(&self, other: &Self) -> Ordering {
784 self.0.as_ref().cmp(other.0.as_ref())
785 }
786}
787
788unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
791
792unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
795
796impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
797where
798 Self: Clone,
799 U: ArraySize,
800{
801 type Error = TryFromSliceError;
802
803 #[inline]
804 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
805 <&'a Self>::try_from(slice).cloned()
806 }
807}
808
809impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
810where
811 U: ArraySize,
812{
813 type Error = TryFromSliceError;
814
815 #[inline]
816 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
817 check_slice_length::<T, U>(slice)?;
818
819 Ok(unsafe { &*slice.as_ptr().cast() })
822 }
823}
824
825impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
826where
827 U: ArraySize,
828{
829 type Error = TryFromSliceError;
830
831 #[inline]
832 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
833 check_slice_length::<T, U>(slice)?;
834
835 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
838 }
839}
840
841#[cfg(feature = "bytemuck")]
842unsafe impl<T, U> Pod for Array<T, U>
843where
844 T: Pod,
845 U: ArraySize,
846 U::ArrayType<T>: Copy,
847{
848}
849
850#[cfg(feature = "bytemuck")]
851unsafe impl<T, U> Zeroable for Array<T, U>
852where
853 T: Zeroable,
854 U: ArraySize,
855{
856}
857
858#[cfg(feature = "zeroize")]
859impl<T, U> Zeroize for Array<T, U>
860where
861 T: Zeroize,
862 U: ArraySize,
863{
864 #[inline]
865 fn zeroize(&mut self) {
866 self.0.as_mut().iter_mut().zeroize()
867 }
868}
869
870#[cfg(feature = "zeroize")]
871impl<T, U> ZeroizeOnDrop for Array<T, U>
872where
873 T: ZeroizeOnDrop,
874 U: ArraySize,
875{
876}
877
878#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
880fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
881 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
882
883 if slice.len() != U::USIZE {
884 <&[T; 1]>::try_from([].as_slice())?;
886
887 #[cfg(debug_assertions)]
888 unreachable!();
889 }
890
891 Ok(())
892}