1#![no_std]
2#![cfg_attr(docsrs, feature(doc_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
132#[cfg(feature = "wincode")]
133mod wincode;
134
135pub use crate::{iter::TryFromIteratorError, traits::*};
136pub use typenum;
137
138use core::{
139 array::TryFromSliceError,
140 borrow::{Borrow, BorrowMut},
141 cmp::Ordering,
142 fmt::{self, Debug},
143 hash::{Hash, Hasher},
144 mem::{self, ManuallyDrop, MaybeUninit},
145 ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
146 ptr,
147 slice::{self, Iter, IterMut},
148};
149use typenum::{Diff, Sum};
150
151#[cfg(feature = "arbitrary")]
152use arbitrary::Arbitrary;
153
154#[cfg(feature = "bytemuck")]
155use bytemuck::{Pod, Zeroable};
156
157#[cfg(feature = "subtle")]
158use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
159
160#[cfg(feature = "zeroize")]
161use zeroize::{Zeroize, ZeroizeOnDrop};
162
163pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
165
166#[repr(transparent)]
181pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
182
183type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
184type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
185type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
186
187impl<T, U> Array<T, U>
188where
189 U: ArraySize,
190{
191 #[inline]
193 pub const fn as_slice(&self) -> &[T] {
194 unsafe { slice::from_raw_parts(self.as_ptr(), U::USIZE) }
197 }
198
199 #[inline]
201 pub const fn as_mut_slice(&mut self) -> &mut [T] {
202 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), U::USIZE) }
205 }
206
207 #[allow(trivial_casts)]
209 pub const fn as_ptr(&self) -> *const T {
210 self as *const Self as *const T
211 }
212
213 #[allow(trivial_casts)]
215 pub const fn as_mut_ptr(&mut self) -> *mut T {
216 self as *mut Self as *mut T
217 }
218
219 #[inline]
221 pub fn iter(&self) -> Iter<'_, T> {
222 self.as_slice().iter()
223 }
224
225 #[inline]
227 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
228 self.as_mut().iter_mut()
229 }
230
231 pub fn map<F, O>(self, f: F) -> Array<O, U>
234 where
235 F: FnMut(T) -> O,
236 {
237 self.into_iter().map(f).collect()
238 }
239
240 #[inline]
242 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
243 where
244 N: ArraySize,
245 U: Add<N>,
246 Sum<U, N>: ArraySize,
247 {
248 let mut c = Array::uninit();
249 let (left, right) = c.split_at_mut(self.len());
250 for (val, dst) in self.into_iter().zip(left) {
251 dst.write(val);
252 }
253 for (val, dst) in other.into_iter().zip(right) {
254 dst.write(val);
255 }
256 unsafe { c.assume_init() }
258 }
259
260 #[inline]
264 pub fn split<N>(self) -> SplitResult<T, U, N>
265 where
266 U: Sub<N>,
267 N: ArraySize,
268 Diff<U, N>: ArraySize,
269 {
270 unsafe {
271 let array = ManuallyDrop::new(self);
272 let head = ptr::read(array.as_ptr().cast());
273 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
274 (head, tail)
275 }
276 }
277
278 #[inline]
280 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
281 where
282 U: Sub<N>,
283 N: ArraySize,
284 Diff<U, N>: ArraySize,
285 {
286 unsafe {
287 let array_ptr = self.as_ptr();
288 let head = &*array_ptr.cast();
289 let tail = &*array_ptr.add(N::USIZE).cast();
290 (head, tail)
291 }
292 }
293
294 #[inline]
296 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
297 where
298 U: Sub<N>,
299 N: ArraySize,
300 Diff<U, N>: ArraySize,
301 {
302 unsafe {
303 let array_ptr = self.as_mut_ptr();
304 let head = &mut *array_ptr.cast();
305 let tail = &mut *array_ptr.add(N::USIZE).cast();
306 (head, tail)
307 }
308 }
309
310 #[allow(clippy::arithmetic_side_effects)]
316 #[inline]
317 pub const fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
318 assert!(U::USIZE != 0, "chunk size must be non-zero");
319 let chunks_len = buf.len() / U::USIZE;
323 let tail_pos = U::USIZE * chunks_len;
324 let tail_len = buf.len() - tail_pos;
325 unsafe {
326 let ptr = buf.as_ptr();
327 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
328 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
329 (chunks, tail)
330 }
331 }
332
333 #[allow(clippy::arithmetic_side_effects)]
339 #[inline]
340 pub const fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
341 assert!(U::USIZE != 0, "chunk size must be non-zero");
342 let chunks_len = buf.len() / U::USIZE;
346 let tail_pos = U::USIZE * chunks_len;
347 let tail_len = buf.len() - tail_pos;
348 unsafe {
349 let ptr = buf.as_mut_ptr();
350 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
351 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
352 (chunks, tail)
353 }
354 }
355
356 #[inline]
358 pub const fn slice_as_flattened(slice: &[Self]) -> &[T] {
359 let len = slice
360 .len()
361 .checked_mul(U::USIZE)
362 .expect("slice len overflow");
363
364 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), len) }
367 }
368
369 #[inline]
371 pub const fn slice_as_flattened_mut(slice: &mut [Self]) -> &mut [T] {
372 let len = slice
373 .len()
374 .checked_mul(U::USIZE)
375 .expect("slice len overflow");
376
377 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) }
380 }
381}
382
383impl<T, U, V> Array<Array<T, U>, V>
384where
385 U: ArraySize,
386 V: ArraySize,
387{
388 pub const fn as_flattened(&self) -> &[T] {
419 Array::slice_as_flattened(self.as_slice())
420 }
421
422 pub const fn as_flattened_mut(&mut self) -> &mut [T] {
448 Array::slice_as_flattened_mut(self.as_mut_slice())
449 }
450}
451
452impl<T, U, const N: usize> Array<T, U>
454where
455 U: ArraySize<ArrayType<T> = [T; N]>,
456{
457 #[inline]
459 pub const fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
460 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
462 }
463
464 #[inline]
466 pub const fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
467 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
469 }
470
471 #[inline]
473 pub const fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
474 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
476 }
477
478 #[inline]
480 pub const fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
481 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
483 }
484}
485
486impl<T, U> Array<MaybeUninit<T>, U>
487where
488 U: ArraySize,
489{
490 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
492 #[allow(clippy::uninit_assumed_init)]
501 Self(unsafe { MaybeUninit::uninit().assume_init() })
502 }
503
504 #[inline]
511 pub unsafe fn assume_init(self) -> Array<T, U> {
512 unsafe {
513 mem::transmute_copy(&self)
525 }
526 }
527}
528
529impl<T, U> AsRef<Array<T, U>> for Array<T, U>
530where
531 U: ArraySize,
532{
533 #[inline]
534 fn as_ref(&self) -> &Self {
535 self
536 }
537}
538
539impl<T, U> AsRef<[T]> for Array<T, U>
540where
541 U: ArraySize,
542{
543 #[inline]
544 fn as_ref(&self) -> &[T] {
545 self.0.as_ref()
546 }
547}
548
549impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
550where
551 U: ArraySize<ArrayType<T> = [T; N]>,
552{
553 #[inline]
554 fn as_ref(&self) -> &[T; N] {
555 &self.0
556 }
557}
558
559impl<T, U> AsMut<[T]> for Array<T, U>
560where
561 U: ArraySize,
562{
563 #[inline]
564 fn as_mut(&mut self) -> &mut [T] {
565 self.0.as_mut()
566 }
567}
568
569impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
570where
571 U: ArraySize<ArrayType<T> = [T; N]>,
572{
573 #[inline]
574 fn as_mut(&mut self) -> &mut [T; N] {
575 &mut self.0
576 }
577}
578
579impl<T, U> Borrow<[T]> for Array<T, U>
580where
581 U: ArraySize,
582{
583 #[inline]
584 fn borrow(&self) -> &[T] {
585 self.0.as_ref()
586 }
587}
588
589impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
590where
591 U: ArraySize<ArrayType<T> = [T; N]>,
592{
593 #[inline]
594 fn borrow(&self) -> &[T; N] {
595 &self.0
596 }
597}
598
599impl<T, U> BorrowMut<[T]> for Array<T, U>
600where
601 U: ArraySize,
602{
603 #[inline]
604 fn borrow_mut(&mut self) -> &mut [T] {
605 self.0.as_mut()
606 }
607}
608
609impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
610where
611 U: ArraySize<ArrayType<T> = [T; N]>,
612{
613 #[inline]
614 fn borrow_mut(&mut self) -> &mut [T; N] {
615 &mut self.0
616 }
617}
618
619impl<T, U> Clone for Array<T, U>
620where
621 T: Clone,
622 U: ArraySize,
623{
624 #[inline]
625 fn clone(&self) -> Self {
626 Self::from_fn(|n| self.0.as_ref()[n].clone())
627 }
628}
629
630impl<T, U> Copy for Array<T, U>
631where
632 T: Copy,
633 U: ArraySize,
634 U::ArrayType<T>: Copy,
635{
636}
637
638impl<T, U> Debug for Array<T, U>
639where
640 T: Debug,
641 U: ArraySize,
642{
643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
645 }
646}
647
648impl<T, U> Default for Array<T, U>
649where
650 T: Default,
651 U: ArraySize,
652{
653 #[inline]
654 fn default() -> Self {
655 Self::from_fn(|_| Default::default())
656 }
657}
658
659impl<T, U> Deref for Array<T, U>
660where
661 U: ArraySize,
662{
663 type Target = [T];
664
665 #[inline]
666 fn deref(&self) -> &[T] {
667 self.0.as_ref()
668 }
669}
670
671impl<T, U> DerefMut for Array<T, U>
672where
673 U: ArraySize,
674{
675 #[inline]
676 fn deref_mut(&mut self) -> &mut [T] {
677 self.0.as_mut()
678 }
679}
680
681impl<T, U> Eq for Array<T, U>
682where
683 T: Eq,
684 U: ArraySize,
685{
686}
687
688impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
689where
690 U: ArraySize<ArrayType<T> = [T; N]>,
691{
692 #[inline]
693 fn from(arr: [T; N]) -> Array<T, U> {
694 Array(arr)
695 }
696}
697
698impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
699where
700 U: ArraySize<ArrayType<T> = [T; N]>,
701{
702 #[inline]
703 fn from(arr: Array<T, U>) -> [T; N] {
704 arr.0
705 }
706}
707
708impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
709where
710 U: ArraySize<ArrayType<T> = [T; N]>,
711{
712 #[inline]
713 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
714 unsafe { &*array_ref.as_ptr().cast() }
716 }
717}
718
719impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
720where
721 U: ArraySize<ArrayType<T> = [T; N]>,
722{
723 #[inline]
724 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
725 array_ref.as_ref()
726 }
727}
728
729impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
730where
731 U: ArraySize<ArrayType<T> = [T; N]>,
732{
733 #[inline]
734 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
735 unsafe { &mut *array_ref.as_mut_ptr().cast() }
737 }
738}
739
740impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
741where
742 U: ArraySize<ArrayType<T> = [T; N]>,
743{
744 #[inline]
745 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
746 array_ref.as_mut()
747 }
748}
749
750#[cfg(feature = "alloc")]
751impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
752where
753 U: ArraySize,
754{
755 #[inline]
756 fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
757 array.into_iter().collect()
758 }
759}
760
761#[cfg(feature = "alloc")]
762impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
763where
764 T: Clone,
765 U: ArraySize,
766{
767 #[inline]
768 fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
769 array.as_slice().into()
770 }
771}
772
773#[cfg(feature = "alloc")]
774impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
775where
776 U: ArraySize,
777{
778 #[inline]
779 fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
780 array.into_iter().collect()
781 }
782}
783
784#[cfg(feature = "alloc")]
785impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
786where
787 T: Clone,
788 U: ArraySize,
789{
790 #[inline]
791 fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
792 array.as_slice().into()
793 }
794}
795
796impl<T, U> Hash for Array<T, U>
797where
798 T: Hash,
799 U: ArraySize,
800{
801 #[inline]
802 fn hash<H: Hasher>(&self, state: &mut H) {
803 self.0.as_ref().hash(state);
804 }
805}
806
807impl<T, I, U> Index<I> for Array<T, U>
808where
809 [T]: Index<I>,
810 U: ArraySize,
811{
812 type Output = <[T] as Index<I>>::Output;
813
814 #[inline]
815 fn index(&self, index: I) -> &Self::Output {
816 Index::index(self.as_slice(), index)
817 }
818}
819
820impl<T, I, U> IndexMut<I> for Array<T, U>
821where
822 [T]: IndexMut<I>,
823 U: ArraySize,
824{
825 #[inline]
826 fn index_mut(&mut self, index: I) -> &mut Self::Output {
827 IndexMut::index_mut(self.as_mut_slice(), index)
828 }
829}
830
831impl<T, U> PartialEq for Array<T, U>
832where
833 T: PartialEq,
834 U: ArraySize,
835{
836 #[inline]
837 fn eq(&self, other: &Self) -> bool {
838 self.0.as_ref().eq(other.0.as_ref())
839 }
840}
841
842impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
843where
844 T: PartialEq,
845 U: ArraySize<ArrayType<T> = [T; N]>,
846{
847 #[inline]
848 fn eq(&self, other: &[T; N]) -> bool {
849 self.0.eq(other)
850 }
851}
852
853impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
854where
855 T: PartialEq,
856 U: ArraySize<ArrayType<T> = [T; N]>,
857{
858 #[inline]
859 fn eq(&self, other: &Array<T, U>) -> bool {
860 self.eq(&other.0)
861 }
862}
863
864impl<T, U> PartialOrd for Array<T, U>
865where
866 T: PartialOrd,
867 U: ArraySize,
868{
869 #[inline]
870 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
871 self.0.as_ref().partial_cmp(other.0.as_ref())
872 }
873}
874
875impl<T, U> Ord for Array<T, U>
876where
877 T: Ord,
878 U: ArraySize,
879{
880 #[inline]
881 fn cmp(&self, other: &Self) -> Ordering {
882 self.0.as_ref().cmp(other.0.as_ref())
883 }
884}
885
886unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
889
890unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
893
894impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
895where
896 Self: Clone,
897 U: ArraySize,
898{
899 type Error = TryFromSliceError;
900
901 #[inline]
902 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
903 <&'a Self>::try_from(slice).cloned()
904 }
905}
906
907#[cfg(feature = "alloc")]
908impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
909where
910 Self: Clone,
911 U: ArraySize,
912{
913 type Error = TryFromSliceError;
914
915 #[inline]
916 fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
917 Self::try_from(&*b)
918 }
919}
920
921#[cfg(feature = "alloc")]
922impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
923where
924 Self: Clone,
925 U: ArraySize,
926{
927 type Error = TryFromSliceError;
928
929 #[inline]
930 fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
931 Self::try_from(&**b)
932 }
933}
934
935#[cfg(feature = "alloc")]
936impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
937where
938 Self: Clone,
939 U: ArraySize,
940{
941 type Error = TryFromSliceError;
942
943 #[inline]
944 fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
945 Self::try_from(v.as_slice())
946 }
947}
948
949#[cfg(feature = "alloc")]
950impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
951where
952 Self: Clone,
953 U: ArraySize,
954{
955 type Error = TryFromSliceError;
956
957 #[inline]
958 fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
959 Self::try_from(v.as_slice())
960 }
961}
962
963impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
964where
965 U: ArraySize,
966{
967 type Error = TryFromSliceError;
968
969 #[inline]
970 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
971 check_slice_length::<T, U>(slice)?;
972
973 Ok(unsafe { &*slice.as_ptr().cast() })
976 }
977}
978
979impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
980where
981 U: ArraySize,
982{
983 type Error = TryFromSliceError;
984
985 #[inline]
986 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
987 check_slice_length::<T, U>(slice)?;
988
989 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
992 }
993}
994
995impl<T, U> Array<T, U>
997where
998 U: ArraySize,
999{
1000 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1006 #[inline]
1007 pub fn from_slice(slice: &[T]) -> &Self {
1008 slice.try_into().expect("slice length mismatch")
1009 }
1010
1011 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1017 #[inline]
1018 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
1019 slice.try_into().expect("slice length mismatch")
1020 }
1021
1022 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1028 #[inline]
1029 pub fn clone_from_slice(slice: &[T]) -> Self
1030 where
1031 Self: Clone,
1032 {
1033 slice.try_into().expect("slice length mismatch")
1034 }
1035}
1036
1037#[cfg(feature = "arbitrary")]
1038impl<'a, T, U> Arbitrary<'a> for Array<T, U>
1039where
1040 T: Arbitrary<'a>,
1041 U: ArraySize,
1042{
1043 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1044 Self::try_from_fn(|_n| Arbitrary::arbitrary(u))
1045 }
1046}
1047
1048#[cfg(feature = "bytemuck")]
1049unsafe impl<T, U> Pod for Array<T, U>
1050where
1051 T: Pod,
1052 U: ArraySize,
1053 U::ArrayType<T>: Copy,
1054{
1055}
1056
1057#[cfg(feature = "bytemuck")]
1058unsafe impl<T, U> Zeroable for Array<T, U>
1059where
1060 T: Zeroable,
1061 U: ArraySize,
1062{
1063}
1064
1065#[cfg(feature = "subtle")]
1066impl<T, U> ConditionallySelectable for Array<T, U>
1067where
1068 Self: Copy,
1069 T: ConditionallySelectable,
1070 U: ArraySize,
1071{
1072 #[inline]
1073 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
1074 let mut output = *a;
1075 output.conditional_assign(b, choice);
1076 output
1077 }
1078
1079 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
1080 for (a_i, b_i) in self.iter_mut().zip(other) {
1081 a_i.conditional_assign(b_i, choice)
1082 }
1083 }
1084}
1085
1086#[cfg(feature = "subtle")]
1087impl<T, U> ConstantTimeEq for Array<T, U>
1088where
1089 T: ConstantTimeEq,
1090 U: ArraySize,
1091{
1092 #[inline]
1093 fn ct_eq(&self, other: &Self) -> Choice {
1094 self.iter()
1095 .zip(other.iter())
1096 .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
1097 }
1098}
1099
1100#[cfg(feature = "zeroize")]
1101impl<T, U> Zeroize for Array<T, U>
1102where
1103 T: Zeroize,
1104 U: ArraySize,
1105{
1106 #[inline]
1107 fn zeroize(&mut self) {
1108 self.0.as_mut().iter_mut().zeroize()
1109 }
1110}
1111
1112#[cfg(feature = "zeroize")]
1113impl<T, U> ZeroizeOnDrop for Array<T, U>
1114where
1115 T: ZeroizeOnDrop,
1116 U: ArraySize,
1117{
1118}
1119
1120#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
1122fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
1123 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
1124
1125 if slice.len() != U::USIZE {
1126 <&[T; 1]>::try_from([].as_slice())?;
1128
1129 #[cfg(debug_assertions)]
1130 unreachable!();
1131 }
1132
1133 Ok(())
1134}