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