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 trivial_casts,
26 trivial_numeric_casts,
27 unused_lifetimes,
28 unused_qualifications
29)]
30
31#[cfg(feature = "alloc")]
121extern crate alloc;
122
123pub mod sizes;
124
125mod from_fn;
126mod iter;
127mod traits;
128
129#[cfg(feature = "serde")]
130mod serde;
131
132pub use crate::{iter::TryFromIteratorError, traits::*};
133pub use typenum;
134
135use core::{
136 array::TryFromSliceError,
137 borrow::{Borrow, BorrowMut},
138 cmp::Ordering,
139 fmt::{self, Debug},
140 hash::{Hash, Hasher},
141 mem::{self, ManuallyDrop, MaybeUninit},
142 ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
143 ptr,
144 slice::{self, Iter, IterMut},
145};
146use typenum::{Diff, Sum};
147
148#[cfg(feature = "bytemuck")]
149use bytemuck::{Pod, Zeroable};
150
151#[cfg(feature = "subtle")]
152use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
153
154#[cfg(feature = "zeroize")]
155use zeroize::{Zeroize, ZeroizeOnDrop};
156
157pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
159
160#[repr(transparent)]
175pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
176
177type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
178type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
179type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
180
181impl<T, U> Array<T, U>
182where
183 U: ArraySize,
184{
185 #[inline]
187 pub fn as_slice(&self) -> &[T] {
188 self.0.as_ref()
189 }
190
191 #[inline]
193 pub fn as_mut_slice(&mut self) -> &mut [T] {
194 self.0.as_mut()
195 }
196
197 #[inline]
199 pub fn iter(&self) -> Iter<'_, T> {
200 self.as_slice().iter()
201 }
202
203 #[inline]
205 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
206 self.as_mut().iter_mut()
207 }
208
209 pub fn map<F, O>(self, f: F) -> Array<O, U>
212 where
213 F: FnMut(T) -> O,
214 {
215 self.into_iter().map(f).collect()
216 }
217
218 #[inline]
220 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
221 where
222 N: ArraySize,
223 U: Add<N>,
224 Sum<U, N>: ArraySize,
225 {
226 let mut c = Array::uninit();
227 let (left, right) = c.split_at_mut(self.len());
228 for (val, dst) in self.into_iter().zip(left) {
229 dst.write(val);
230 }
231 for (val, dst) in other.into_iter().zip(right) {
232 dst.write(val);
233 }
234 unsafe { c.assume_init() }
236 }
237
238 #[inline]
242 pub fn split<N>(self) -> SplitResult<T, U, N>
243 where
244 U: Sub<N>,
245 N: ArraySize,
246 Diff<U, N>: ArraySize,
247 {
248 unsafe {
249 let array = ManuallyDrop::new(self);
250 let head = ptr::read(array.as_ptr().cast());
251 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
252 (head, tail)
253 }
254 }
255
256 #[inline]
258 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
259 where
260 U: Sub<N>,
261 N: ArraySize,
262 Diff<U, N>: ArraySize,
263 {
264 unsafe {
265 let array_ptr = self.as_ptr();
266 let head = &*array_ptr.cast();
267 let tail = &*array_ptr.add(N::USIZE).cast();
268 (head, tail)
269 }
270 }
271
272 #[inline]
274 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
275 where
276 U: Sub<N>,
277 N: ArraySize,
278 Diff<U, N>: ArraySize,
279 {
280 unsafe {
281 let array_ptr = self.as_mut_ptr();
282 let head = &mut *array_ptr.cast();
283 let tail = &mut *array_ptr.add(N::USIZE).cast();
284 (head, tail)
285 }
286 }
287
288 #[allow(clippy::arithmetic_side_effects)]
294 #[inline]
295 pub fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
296 assert_ne!(U::USIZE, 0, "chunk size must be non-zero");
297 let chunks_len = buf.len() / U::USIZE;
301 let tail_pos = U::USIZE * chunks_len;
302 let tail_len = buf.len() - tail_pos;
303 unsafe {
304 let ptr = buf.as_ptr();
305 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
306 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
307 (chunks, tail)
308 }
309 }
310
311 #[allow(clippy::arithmetic_side_effects)]
317 #[inline]
318 pub fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
319 assert_ne!(U::USIZE, 0, "chunk size must be non-zero");
320 let chunks_len = buf.len() / U::USIZE;
324 let tail_pos = U::USIZE * chunks_len;
325 let tail_len = buf.len() - tail_pos;
326 unsafe {
327 let ptr = buf.as_mut_ptr();
328 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
329 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
330 (chunks, tail)
331 }
332 }
333
334 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
340 #[inline]
341 pub fn from_slice(slice: &[T]) -> &Self {
342 slice.try_into().expect("slice length mismatch")
343 }
344
345 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
351 #[inline]
352 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
353 slice.try_into().expect("slice length mismatch")
354 }
355
356 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
362 #[inline]
363 pub fn clone_from_slice(slice: &[T]) -> Self
364 where
365 Self: Clone,
366 {
367 slice.try_into().expect("slice length mismatch")
368 }
369}
370
371impl<T, U, const N: usize> Array<T, U>
373where
374 U: ArraySize<ArrayType<T> = [T; N]>,
375{
376 #[inline]
378 pub fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
379 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
381 }
382
383 #[inline]
385 pub fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
386 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
388 }
389
390 #[inline]
392 pub fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
393 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
395 }
396
397 #[inline]
399 pub fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
400 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
402 }
403}
404
405impl<T, U> Array<MaybeUninit<T>, U>
406where
407 U: ArraySize,
408{
409 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
411 #[allow(clippy::uninit_assumed_init)]
420 Self(unsafe { MaybeUninit::uninit().assume_init() })
421 }
422
423 #[inline]
430 pub unsafe fn assume_init(self) -> Array<T, U> {
431 unsafe {
432 mem::transmute_copy(&self)
444 }
445 }
446}
447
448impl<T, U> AsRef<Array<T, U>> for Array<T, U>
449where
450 U: ArraySize,
451{
452 #[inline]
453 fn as_ref(&self) -> &Self {
454 self
455 }
456}
457
458impl<T, U> AsRef<[T]> for Array<T, U>
459where
460 U: ArraySize,
461{
462 #[inline]
463 fn as_ref(&self) -> &[T] {
464 self.0.as_ref()
465 }
466}
467
468impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
469where
470 U: ArraySize<ArrayType<T> = [T; N]>,
471{
472 #[inline]
473 fn as_ref(&self) -> &[T; N] {
474 &self.0
475 }
476}
477
478impl<T, U> AsMut<[T]> for Array<T, U>
479where
480 U: ArraySize,
481{
482 #[inline]
483 fn as_mut(&mut self) -> &mut [T] {
484 self.0.as_mut()
485 }
486}
487
488impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
489where
490 U: ArraySize<ArrayType<T> = [T; N]>,
491{
492 #[inline]
493 fn as_mut(&mut self) -> &mut [T; N] {
494 &mut self.0
495 }
496}
497
498impl<T, U> Borrow<[T]> for Array<T, U>
499where
500 U: ArraySize,
501{
502 #[inline]
503 fn borrow(&self) -> &[T] {
504 self.0.as_ref()
505 }
506}
507
508impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
509where
510 U: ArraySize<ArrayType<T> = [T; N]>,
511{
512 #[inline]
513 fn borrow(&self) -> &[T; N] {
514 &self.0
515 }
516}
517
518impl<T, U> BorrowMut<[T]> for Array<T, U>
519where
520 U: ArraySize,
521{
522 #[inline]
523 fn borrow_mut(&mut self) -> &mut [T] {
524 self.0.as_mut()
525 }
526}
527
528impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
529where
530 U: ArraySize<ArrayType<T> = [T; N]>,
531{
532 #[inline]
533 fn borrow_mut(&mut self) -> &mut [T; N] {
534 &mut self.0
535 }
536}
537
538impl<T, U> Clone for Array<T, U>
539where
540 T: Clone,
541 U: ArraySize,
542{
543 #[inline]
544 fn clone(&self) -> Self {
545 Self::from_fn(|n| self.0.as_ref()[n].clone())
546 }
547}
548
549impl<T, U> Copy for Array<T, U>
550where
551 T: Copy,
552 U: ArraySize,
553 U::ArrayType<T>: Copy,
554{
555}
556
557impl<T, U> Debug for Array<T, U>
558where
559 T: Debug,
560 U: ArraySize,
561{
562 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
564 }
565}
566
567impl<T, U> Default for Array<T, U>
568where
569 T: Default,
570 U: ArraySize,
571{
572 #[inline]
573 fn default() -> Self {
574 Self::from_fn(|_| Default::default())
575 }
576}
577
578impl<T, U> Deref for Array<T, U>
579where
580 U: ArraySize,
581{
582 type Target = [T];
583
584 #[inline]
585 fn deref(&self) -> &[T] {
586 self.0.as_ref()
587 }
588}
589
590impl<T, U> DerefMut for Array<T, U>
591where
592 U: ArraySize,
593{
594 #[inline]
595 fn deref_mut(&mut self) -> &mut [T] {
596 self.0.as_mut()
597 }
598}
599
600impl<T, U> Eq for Array<T, U>
601where
602 T: Eq,
603 U: ArraySize,
604{
605}
606
607impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
608where
609 U: ArraySize<ArrayType<T> = [T; N]>,
610{
611 #[inline]
612 fn from(arr: [T; N]) -> Array<T, U> {
613 Array(arr)
614 }
615}
616
617impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
618where
619 U: ArraySize<ArrayType<T> = [T; N]>,
620{
621 #[inline]
622 fn from(arr: Array<T, U>) -> [T; N] {
623 arr.0
624 }
625}
626
627impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
628where
629 U: ArraySize<ArrayType<T> = [T; N]>,
630{
631 #[inline]
632 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
633 unsafe { &*array_ref.as_ptr().cast() }
635 }
636}
637
638impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
639where
640 U: ArraySize<ArrayType<T> = [T; N]>,
641{
642 #[inline]
643 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
644 array_ref.as_ref()
645 }
646}
647
648impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
649where
650 U: ArraySize<ArrayType<T> = [T; N]>,
651{
652 #[inline]
653 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
654 unsafe { &mut *array_ref.as_mut_ptr().cast() }
656 }
657}
658
659impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
660where
661 U: ArraySize<ArrayType<T> = [T; N]>,
662{
663 #[inline]
664 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
665 array_ref.as_mut()
666 }
667}
668
669#[cfg(feature = "alloc")]
670impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
671where
672 U: ArraySize,
673{
674 #[inline]
675 fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
676 array.into_iter().collect()
677 }
678}
679
680#[cfg(feature = "alloc")]
681impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
682where
683 T: Clone,
684 U: ArraySize,
685{
686 #[inline]
687 fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
688 array.as_slice().into()
689 }
690}
691
692#[cfg(feature = "alloc")]
693impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
694where
695 U: ArraySize,
696{
697 #[inline]
698 fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
699 array.into_iter().collect()
700 }
701}
702
703#[cfg(feature = "alloc")]
704impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
705where
706 T: Clone,
707 U: ArraySize,
708{
709 #[inline]
710 fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
711 array.as_slice().into()
712 }
713}
714
715impl<T, U> Hash for Array<T, U>
716where
717 T: Hash,
718 U: ArraySize,
719{
720 #[inline]
721 fn hash<H: Hasher>(&self, state: &mut H) {
722 self.0.as_ref().hash(state);
723 }
724}
725
726impl<T, I, U> Index<I> for Array<T, U>
727where
728 [T]: Index<I>,
729 U: ArraySize,
730{
731 type Output = <[T] as Index<I>>::Output;
732
733 #[inline]
734 fn index(&self, index: I) -> &Self::Output {
735 Index::index(self.as_slice(), index)
736 }
737}
738
739impl<T, I, U> IndexMut<I> for Array<T, U>
740where
741 [T]: IndexMut<I>,
742 U: ArraySize,
743{
744 #[inline]
745 fn index_mut(&mut self, index: I) -> &mut Self::Output {
746 IndexMut::index_mut(self.as_mut_slice(), index)
747 }
748}
749
750impl<T, U> PartialEq for Array<T, U>
751where
752 T: PartialEq,
753 U: ArraySize,
754{
755 #[inline]
756 fn eq(&self, other: &Self) -> bool {
757 self.0.as_ref().eq(other.0.as_ref())
758 }
759}
760
761impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
762where
763 T: PartialEq,
764 U: ArraySize<ArrayType<T> = [T; N]>,
765{
766 #[inline]
767 fn eq(&self, other: &[T; N]) -> bool {
768 self.0.eq(other)
769 }
770}
771
772impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
773where
774 T: PartialEq,
775 U: ArraySize<ArrayType<T> = [T; N]>,
776{
777 #[inline]
778 fn eq(&self, other: &Array<T, U>) -> bool {
779 self.eq(&other.0)
780 }
781}
782
783impl<T, U> PartialOrd for Array<T, U>
784where
785 T: PartialOrd,
786 U: ArraySize,
787{
788 #[inline]
789 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
790 self.0.as_ref().partial_cmp(other.0.as_ref())
791 }
792}
793
794impl<T, U> Ord for Array<T, U>
795where
796 T: Ord,
797 U: ArraySize,
798{
799 #[inline]
800 fn cmp(&self, other: &Self) -> Ordering {
801 self.0.as_ref().cmp(other.0.as_ref())
802 }
803}
804
805unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
808
809unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
812
813impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
814where
815 Self: Clone,
816 U: ArraySize,
817{
818 type Error = TryFromSliceError;
819
820 #[inline]
821 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
822 <&'a Self>::try_from(slice).cloned()
823 }
824}
825
826#[cfg(feature = "alloc")]
827impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
828where
829 Self: Clone,
830 U: ArraySize,
831{
832 type Error = TryFromSliceError;
833
834 #[inline]
835 fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
836 Self::try_from(&*b)
837 }
838}
839
840#[cfg(feature = "alloc")]
841impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
842where
843 Self: Clone,
844 U: ArraySize,
845{
846 type Error = TryFromSliceError;
847
848 #[inline]
849 fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
850 Self::try_from(&**b)
851 }
852}
853
854#[cfg(feature = "alloc")]
855impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
856where
857 Self: Clone,
858 U: ArraySize,
859{
860 type Error = TryFromSliceError;
861
862 #[inline]
863 fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
864 Self::try_from(v.as_slice())
865 }
866}
867
868#[cfg(feature = "alloc")]
869impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
870where
871 Self: Clone,
872 U: ArraySize,
873{
874 type Error = TryFromSliceError;
875
876 #[inline]
877 fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
878 Self::try_from(v.as_slice())
879 }
880}
881
882impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
883where
884 U: ArraySize,
885{
886 type Error = TryFromSliceError;
887
888 #[inline]
889 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
890 check_slice_length::<T, U>(slice)?;
891
892 Ok(unsafe { &*slice.as_ptr().cast() })
895 }
896}
897
898impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
899where
900 U: ArraySize,
901{
902 type Error = TryFromSliceError;
903
904 #[inline]
905 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
906 check_slice_length::<T, U>(slice)?;
907
908 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
911 }
912}
913
914#[cfg(feature = "bytemuck")]
915unsafe impl<T, U> Pod for Array<T, U>
916where
917 T: Pod,
918 U: ArraySize,
919 U::ArrayType<T>: Copy,
920{
921}
922
923#[cfg(feature = "bytemuck")]
924unsafe impl<T, U> Zeroable for Array<T, U>
925where
926 T: Zeroable,
927 U: ArraySize,
928{
929}
930
931#[cfg(feature = "subtle")]
932impl<T, U> ConditionallySelectable for Array<T, U>
933where
934 Self: Copy,
935 T: ConditionallySelectable,
936 U: ArraySize,
937{
938 #[inline]
939 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
940 let mut output = *a;
941 output.conditional_assign(b, choice);
942 output
943 }
944
945 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
946 for (a_i, b_i) in self.iter_mut().zip(other) {
947 a_i.conditional_assign(b_i, choice)
948 }
949 }
950}
951
952#[cfg(feature = "subtle")]
953impl<T, U> ConstantTimeEq for Array<T, U>
954where
955 T: ConstantTimeEq,
956 U: ArraySize,
957{
958 #[inline]
959 fn ct_eq(&self, other: &Self) -> Choice {
960 self.iter()
961 .zip(other.iter())
962 .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
963 }
964}
965
966#[cfg(feature = "zeroize")]
967impl<T, U> Zeroize for Array<T, U>
968where
969 T: Zeroize,
970 U: ArraySize,
971{
972 #[inline]
973 fn zeroize(&mut self) {
974 self.0.as_mut().iter_mut().zeroize()
975 }
976}
977
978#[cfg(feature = "zeroize")]
979impl<T, U> ZeroizeOnDrop for Array<T, U>
980where
981 T: ZeroizeOnDrop,
982 U: ArraySize,
983{
984}
985
986#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
988fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
989 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
990
991 if slice.len() != U::USIZE {
992 <&[T; 1]>::try_from([].as_slice())?;
994
995 #[cfg(debug_assertions)]
996 unreachable!();
997 }
998
999 Ok(())
1000}