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