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
9#[cfg(feature = "alloc")]
99extern crate alloc;
100
101pub mod sizes;
102
103mod from_fn;
104mod iter;
105mod traits;
106
107#[cfg(feature = "serde")]
108mod serde;
109
110pub use crate::{iter::TryFromIteratorError, traits::*};
111pub use typenum;
112
113use core::{
114 array::TryFromSliceError,
115 borrow::{Borrow, BorrowMut},
116 cmp::Ordering,
117 fmt::{self, Debug},
118 hash::{Hash, Hasher},
119 mem::{self, ManuallyDrop, MaybeUninit},
120 ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
121 ptr,
122 slice::{self, Iter, IterMut},
123};
124use typenum::{Diff, Sum};
125
126#[cfg(feature = "arbitrary")]
127use arbitrary::Arbitrary;
128
129#[cfg(feature = "bytemuck")]
130use bytemuck::{Pod, Zeroable};
131
132#[cfg(feature = "subtle")]
133use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
134
135#[cfg(feature = "zeroize")]
136use zeroize::{Zeroize, ZeroizeOnDrop};
137
138#[cfg(feature = "zerocopy")]
139use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
140
141pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
143
144#[cfg_attr(
159 feature = "zerocopy",
160 derive(IntoBytes, FromBytes, Immutable, Unaligned, KnownLayout)
161)]
162#[repr(transparent)]
163pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
164
165type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
166type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
167type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
168
169impl<T, U> Array<T, U>
170where
171 U: ArraySize,
172{
173 #[inline]
175 pub const fn as_slice(&self) -> &[T] {
176 unsafe { slice::from_raw_parts(self.as_ptr(), U::USIZE) }
179 }
180
181 #[inline]
183 pub const fn as_mut_slice(&mut self) -> &mut [T] {
184 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), U::USIZE) }
187 }
188
189 pub const fn as_ptr(&self) -> *const T {
191 ptr::from_ref::<Self>(self).cast::<T>()
192 }
193
194 pub const fn as_mut_ptr(&mut self) -> *mut T {
196 ptr::from_mut::<Self>(self).cast::<T>()
197 }
198
199 #[inline]
201 pub fn iter(&self) -> Iter<'_, T> {
202 self.as_slice().iter()
203 }
204
205 #[inline]
207 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
208 self.as_mut().iter_mut()
209 }
210
211 pub fn map<F, O>(self, f: F) -> Array<O, U>
214 where
215 F: FnMut(T) -> O,
216 {
217 self.into_iter().map(f).collect()
218 }
219
220 #[inline]
222 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
223 where
224 N: ArraySize,
225 U: Add<N>,
226 Sum<U, N>: ArraySize,
227 {
228 let mut c = Array::uninit();
229 let (left, right) = c.split_at_mut(self.len());
230 for (val, dst) in self.into_iter().zip(left) {
231 dst.write(val);
232 }
233 for (val, dst) in other.into_iter().zip(right) {
234 dst.write(val);
235 }
236 unsafe { c.assume_init() }
238 }
239
240 #[inline]
244 pub fn split<N>(self) -> SplitResult<T, U, N>
245 where
246 U: Sub<N>,
247 N: ArraySize,
248 Diff<U, N>: ArraySize,
249 {
250 unsafe {
251 let array = ManuallyDrop::new(self);
252 let head = ptr::read(array.as_ptr().cast());
253 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
254 (head, tail)
255 }
256 }
257
258 #[inline]
260 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
261 where
262 U: Sub<N>,
263 N: ArraySize,
264 Diff<U, N>: ArraySize,
265 {
266 unsafe {
267 let array_ptr = self.as_ptr();
268 let head = &*array_ptr.cast();
269 let tail = &*array_ptr.add(N::USIZE).cast();
270 (head, tail)
271 }
272 }
273
274 #[inline]
276 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
277 where
278 U: Sub<N>,
279 N: ArraySize,
280 Diff<U, N>: ArraySize,
281 {
282 unsafe {
283 let array_ptr = self.as_mut_ptr();
284 let head = &mut *array_ptr.cast();
285 let tail = &mut *array_ptr.add(N::USIZE).cast();
286 (head, tail)
287 }
288 }
289
290 #[allow(clippy::arithmetic_side_effects)]
296 #[inline]
297 pub const fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
298 assert!(U::USIZE != 0, "chunk size must be non-zero");
299 let chunks_len = buf.len() / U::USIZE;
303 let tail_pos = U::USIZE * chunks_len;
304 let tail_len = buf.len() - tail_pos;
305 unsafe {
306 let ptr = buf.as_ptr();
307 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
308 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
309 (chunks, tail)
310 }
311 }
312
313 #[allow(clippy::arithmetic_side_effects)]
319 #[inline]
320 pub const fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
321 assert!(U::USIZE != 0, "chunk size must be non-zero");
322 let chunks_len = buf.len() / U::USIZE;
326 let tail_pos = U::USIZE * chunks_len;
327 let tail_len = buf.len() - tail_pos;
328 unsafe {
329 let ptr = buf.as_mut_ptr();
330 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
331 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
332 (chunks, tail)
333 }
334 }
335
336 #[inline]
341 pub const fn slice_as_flattened(slice: &[Self]) -> &[T] {
342 let len = slice
343 .len()
344 .checked_mul(U::USIZE)
345 .expect("slice len overflow");
346
347 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), len) }
350 }
351
352 #[inline]
357 pub const fn slice_as_flattened_mut(slice: &mut [Self]) -> &mut [T] {
358 let len = slice
359 .len()
360 .checked_mul(U::USIZE)
361 .expect("slice len overflow");
362
363 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) }
366 }
367}
368
369impl<T, U, V> Array<Array<T, U>, V>
370where
371 U: ArraySize,
372 V: ArraySize,
373{
374 pub const fn as_flattened(&self) -> &[T] {
405 Array::slice_as_flattened(self.as_slice())
406 }
407
408 pub const fn as_flattened_mut(&mut self) -> &mut [T] {
434 Array::slice_as_flattened_mut(self.as_mut_slice())
435 }
436}
437
438impl<T, U, const N: usize> Array<T, U>
440where
441 U: ArraySize<ArrayType<T> = [T; N]>,
442{
443 #[inline]
445 pub const fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
446 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
448 }
449
450 #[inline]
452 pub const fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
453 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
455 }
456
457 #[inline]
459 pub const fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
460 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
462 }
463
464 #[inline]
466 pub const fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
467 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
469 }
470}
471
472impl<T, U> Array<MaybeUninit<T>, U>
473where
474 U: ArraySize,
475{
476 #[must_use]
478 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
479 #[allow(clippy::uninit_assumed_init)]
488 Self(unsafe { MaybeUninit::uninit().assume_init() })
489 }
490
491 #[inline]
498 pub unsafe fn assume_init(self) -> Array<T, U> {
499 unsafe {
500 mem::transmute_copy(&self)
512 }
513 }
514}
515
516impl<T, U> AsRef<Array<T, U>> for Array<T, U>
517where
518 U: ArraySize,
519{
520 #[inline]
521 fn as_ref(&self) -> &Self {
522 self
523 }
524}
525
526impl<T, U> AsRef<[T]> for Array<T, U>
527where
528 U: ArraySize,
529{
530 #[inline]
531 fn as_ref(&self) -> &[T] {
532 self.0.as_ref()
533 }
534}
535
536impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
537where
538 U: ArraySize<ArrayType<T> = [T; N]>,
539{
540 #[inline]
541 fn as_ref(&self) -> &[T; N] {
542 &self.0
543 }
544}
545
546impl<T, U> AsMut<[T]> for Array<T, U>
547where
548 U: ArraySize,
549{
550 #[inline]
551 fn as_mut(&mut self) -> &mut [T] {
552 self.0.as_mut()
553 }
554}
555
556impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
557where
558 U: ArraySize<ArrayType<T> = [T; N]>,
559{
560 #[inline]
561 fn as_mut(&mut self) -> &mut [T; N] {
562 &mut self.0
563 }
564}
565
566impl<T, U> Borrow<[T]> for Array<T, U>
567where
568 U: ArraySize,
569{
570 #[inline]
571 fn borrow(&self) -> &[T] {
572 self.0.as_ref()
573 }
574}
575
576impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
577where
578 U: ArraySize<ArrayType<T> = [T; N]>,
579{
580 #[inline]
581 fn borrow(&self) -> &[T; N] {
582 &self.0
583 }
584}
585
586impl<T, U> BorrowMut<[T]> for Array<T, U>
587where
588 U: ArraySize,
589{
590 #[inline]
591 fn borrow_mut(&mut self) -> &mut [T] {
592 self.0.as_mut()
593 }
594}
595
596impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
597where
598 U: ArraySize<ArrayType<T> = [T; N]>,
599{
600 #[inline]
601 fn borrow_mut(&mut self) -> &mut [T; N] {
602 &mut self.0
603 }
604}
605
606impl<T, U> Clone for Array<T, U>
607where
608 T: Clone,
609 U: ArraySize,
610{
611 #[inline]
612 fn clone(&self) -> Self {
613 Self::from_fn(|n| self.0.as_ref()[n].clone())
614 }
615}
616
617impl<T, U> Copy for Array<T, U>
618where
619 T: Copy,
620 U: ArraySize,
621 U::ArrayType<T>: Copy,
622{
623}
624
625impl<T, U> Debug for Array<T, U>
626where
627 T: Debug,
628 U: ArraySize,
629{
630 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
631 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
632 }
633}
634
635impl<T, U> Default for Array<T, U>
636where
637 T: Default,
638 U: ArraySize,
639{
640 #[inline]
641 fn default() -> Self {
642 Self::from_fn(|_| Default::default())
643 }
644}
645
646impl<T, U> Deref for Array<T, U>
647where
648 U: ArraySize,
649{
650 type Target = [T];
651
652 #[inline]
653 fn deref(&self) -> &[T] {
654 self.0.as_ref()
655 }
656}
657
658impl<T, U> DerefMut for Array<T, U>
659where
660 U: ArraySize,
661{
662 #[inline]
663 fn deref_mut(&mut self) -> &mut [T] {
664 self.0.as_mut()
665 }
666}
667
668impl<T, U> Eq for Array<T, U>
669where
670 T: Eq,
671 U: ArraySize,
672{
673}
674
675impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
676where
677 U: ArraySize<ArrayType<T> = [T; N]>,
678{
679 #[inline]
680 fn from(arr: [T; N]) -> Array<T, U> {
681 Array(arr)
682 }
683}
684
685impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
686where
687 U: ArraySize<ArrayType<T> = [T; N]>,
688{
689 #[inline]
690 fn from(arr: Array<T, U>) -> [T; N] {
691 arr.0
692 }
693}
694
695impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
696where
697 U: ArraySize<ArrayType<T> = [T; N]>,
698{
699 #[inline]
700 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
701 unsafe { &*array_ref.as_ptr().cast() }
703 }
704}
705
706impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
707where
708 U: ArraySize<ArrayType<T> = [T; N]>,
709{
710 #[inline]
711 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
712 array_ref.as_ref()
713 }
714}
715
716impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
717where
718 U: ArraySize<ArrayType<T> = [T; N]>,
719{
720 #[inline]
721 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
722 unsafe { &mut *array_ref.as_mut_ptr().cast() }
724 }
725}
726
727impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
728where
729 U: ArraySize<ArrayType<T> = [T; N]>,
730{
731 #[inline]
732 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
733 array_ref.as_mut()
734 }
735}
736
737#[cfg(feature = "alloc")]
738impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
739where
740 U: ArraySize,
741{
742 #[inline]
743 fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
744 array.into_iter().collect()
745 }
746}
747
748#[cfg(feature = "alloc")]
749impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
750where
751 T: Clone,
752 U: ArraySize,
753{
754 #[inline]
755 fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
756 array.as_slice().into()
757 }
758}
759
760#[cfg(feature = "alloc")]
761impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
762where
763 U: ArraySize,
764{
765 #[inline]
766 fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
767 array.into_iter().collect()
768 }
769}
770
771#[cfg(feature = "alloc")]
772impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
773where
774 T: Clone,
775 U: ArraySize,
776{
777 #[inline]
778 fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
779 array.as_slice().into()
780 }
781}
782
783impl<T, U> Hash for Array<T, U>
784where
785 T: Hash,
786 U: ArraySize,
787{
788 #[inline]
789 fn hash<H: Hasher>(&self, state: &mut H) {
790 self.0.as_ref().hash(state);
791 }
792}
793
794impl<T, I, U> Index<I> for Array<T, U>
795where
796 [T]: Index<I>,
797 U: ArraySize,
798{
799 type Output = <[T] as Index<I>>::Output;
800
801 #[inline]
802 fn index(&self, index: I) -> &Self::Output {
803 Index::index(self.as_slice(), index)
804 }
805}
806
807impl<T, I, U> IndexMut<I> for Array<T, U>
808where
809 [T]: IndexMut<I>,
810 U: ArraySize,
811{
812 #[inline]
813 fn index_mut(&mut self, index: I) -> &mut Self::Output {
814 IndexMut::index_mut(self.as_mut_slice(), index)
815 }
816}
817
818impl<T, U> PartialEq for Array<T, U>
819where
820 T: PartialEq,
821 U: ArraySize,
822{
823 #[inline]
824 fn eq(&self, other: &Self) -> bool {
825 self.0.as_ref().eq(other.0.as_ref())
826 }
827}
828
829impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
830where
831 T: PartialEq,
832 U: ArraySize<ArrayType<T> = [T; N]>,
833{
834 #[inline]
835 fn eq(&self, other: &[T; N]) -> bool {
836 self.0.eq(other)
837 }
838}
839
840impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
841where
842 T: PartialEq,
843 U: ArraySize<ArrayType<T> = [T; N]>,
844{
845 #[inline]
846 fn eq(&self, other: &Array<T, U>) -> bool {
847 self.eq(&other.0)
848 }
849}
850
851impl<T, U> PartialOrd for Array<T, U>
852where
853 T: PartialOrd,
854 U: ArraySize,
855{
856 #[inline]
857 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
858 self.0.as_ref().partial_cmp(other.0.as_ref())
859 }
860}
861
862impl<T, U> Ord for Array<T, U>
863where
864 T: Ord,
865 U: ArraySize,
866{
867 #[inline]
868 fn cmp(&self, other: &Self) -> Ordering {
869 self.0.as_ref().cmp(other.0.as_ref())
870 }
871}
872
873unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
876
877unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
880
881impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
882where
883 Self: Clone,
884 U: ArraySize,
885{
886 type Error = TryFromSliceError;
887
888 #[inline]
889 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
890 <&'a Self>::try_from(slice).cloned()
891 }
892}
893
894#[cfg(feature = "alloc")]
895impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
896where
897 Self: Clone,
898 U: ArraySize,
899{
900 type Error = TryFromSliceError;
901
902 #[inline]
903 fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
904 Self::try_from(&*b)
905 }
906}
907
908#[cfg(feature = "alloc")]
909impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
910where
911 Self: Clone,
912 U: ArraySize,
913{
914 type Error = TryFromSliceError;
915
916 #[inline]
917 fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
918 Self::try_from(&**b)
919 }
920}
921
922#[cfg(feature = "alloc")]
923impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
924where
925 Self: Clone,
926 U: ArraySize,
927{
928 type Error = TryFromSliceError;
929
930 #[inline]
931 fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
932 Self::try_from(v.as_slice())
933 }
934}
935
936#[cfg(feature = "alloc")]
937impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
938where
939 Self: Clone,
940 U: ArraySize,
941{
942 type Error = TryFromSliceError;
943
944 #[inline]
945 fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
946 Self::try_from(v.as_slice())
947 }
948}
949
950impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
951where
952 U: ArraySize,
953{
954 type Error = TryFromSliceError;
955
956 #[inline]
957 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
958 check_slice_length::<T, U>(slice)?;
959
960 Ok(unsafe { &*slice.as_ptr().cast() })
963 }
964}
965
966impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
967where
968 U: ArraySize,
969{
970 type Error = TryFromSliceError;
971
972 #[inline]
973 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
974 check_slice_length::<T, U>(slice)?;
975
976 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
979 }
980}
981
982impl<T, U> Array<T, U>
984where
985 U: ArraySize,
986{
987 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
993 #[inline]
994 pub fn from_slice(slice: &[T]) -> &Self {
995 slice.try_into().expect("slice length mismatch")
996 }
997
998 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1004 #[inline]
1005 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
1006 slice.try_into().expect("slice length mismatch")
1007 }
1008
1009 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1015 #[inline]
1016 pub fn clone_from_slice(slice: &[T]) -> Self
1017 where
1018 Self: Clone,
1019 {
1020 slice.try_into().expect("slice length mismatch")
1021 }
1022}
1023
1024#[cfg(feature = "arbitrary")]
1025impl<'a, T, U> Arbitrary<'a> for Array<T, U>
1026where
1027 T: Arbitrary<'a>,
1028 U: ArraySize,
1029{
1030 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1031 Self::try_from_fn(|_n| Arbitrary::arbitrary(u))
1032 }
1033}
1034
1035#[cfg(feature = "bytemuck")]
1036unsafe impl<T, U> Pod for Array<T, U>
1037where
1038 T: Pod,
1039 U: ArraySize,
1040 U::ArrayType<T>: Copy,
1041{
1042}
1043
1044#[cfg(feature = "bytemuck")]
1045unsafe impl<T, U> Zeroable for Array<T, U>
1046where
1047 T: Zeroable,
1048 U: ArraySize,
1049{
1050}
1051
1052#[cfg(feature = "subtle")]
1053impl<T, U> ConditionallySelectable for Array<T, U>
1054where
1055 Self: Copy,
1056 T: ConditionallySelectable,
1057 U: ArraySize,
1058{
1059 #[inline]
1060 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
1061 let mut output = *a;
1062 output.conditional_assign(b, choice);
1063 output
1064 }
1065
1066 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
1067 for (a_i, b_i) in self.iter_mut().zip(other) {
1068 a_i.conditional_assign(b_i, choice);
1069 }
1070 }
1071}
1072
1073#[cfg(feature = "subtle")]
1074impl<T, U> ConstantTimeEq for Array<T, U>
1075where
1076 T: ConstantTimeEq,
1077 U: ArraySize,
1078{
1079 #[inline]
1080 fn ct_eq(&self, other: &Self) -> Choice {
1081 self.iter()
1082 .zip(other.iter())
1083 .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
1084 }
1085}
1086
1087#[cfg(feature = "zeroize")]
1088impl<T, U> Zeroize for Array<T, U>
1089where
1090 T: Zeroize,
1091 U: ArraySize,
1092{
1093 #[inline]
1094 fn zeroize(&mut self) {
1095 self.0.as_mut().iter_mut().zeroize();
1096 }
1097}
1098
1099#[cfg(feature = "zeroize")]
1100impl<T, U> ZeroizeOnDrop for Array<T, U>
1101where
1102 T: ZeroizeOnDrop,
1103 U: ArraySize,
1104{
1105}
1106
1107#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
1109fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
1110 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
1111
1112 if slice.len() != U::USIZE {
1113 <&[T; 1]>::try_from([].as_slice())?;
1115
1116 #[cfg(debug_assertions)]
1117 unreachable!();
1118 }
1119
1120 Ok(())
1121}