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 flatten;
104mod from_fn;
105mod iter;
106mod traits;
107
108#[cfg(feature = "serde")]
109mod serde;
110
111pub use crate::{
112 flatten::{Flatten, Unflatten},
113 iter::TryFromIteratorError,
114 traits::*,
115};
116pub use typenum;
117
118use core::{
119 array::TryFromSliceError,
120 borrow::{Borrow, BorrowMut},
121 cmp::Ordering,
122 fmt::{self, Debug},
123 hash::{Hash, Hasher},
124 mem::{self, ManuallyDrop, MaybeUninit},
125 ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
126 ptr,
127 slice::{self, Iter, IterMut},
128};
129use typenum::{Diff, Sum};
130
131#[cfg(feature = "arbitrary")]
132use arbitrary::Arbitrary;
133
134#[cfg(feature = "bytemuck")]
135use bytemuck::{Pod, Zeroable};
136
137#[cfg(feature = "subtle")]
138use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
139
140#[cfg(feature = "zeroize")]
141use zeroize::{Zeroize, ZeroizeOnDrop};
142
143#[cfg(feature = "zerocopy")]
144use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
145
146pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
148
149#[cfg_attr(
164 feature = "zerocopy",
165 derive(IntoBytes, FromBytes, Immutable, Unaligned, KnownLayout)
166)]
167#[repr(transparent)]
168pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
169
170type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
171type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
172type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
173
174impl<T, U> Array<T, U>
175where
176 U: ArraySize,
177{
178 #[inline]
180 pub const fn as_slice(&self) -> &[T] {
181 unsafe { slice::from_raw_parts(self.as_ptr(), U::USIZE) }
184 }
185
186 #[inline]
188 pub const fn as_mut_slice(&mut self) -> &mut [T] {
189 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), U::USIZE) }
192 }
193
194 pub const fn as_ptr(&self) -> *const T {
196 ptr::from_ref::<Self>(self).cast::<T>()
197 }
198
199 pub const fn as_mut_ptr(&mut self) -> *mut T {
201 ptr::from_mut::<Self>(self).cast::<T>()
202 }
203
204 #[inline]
206 pub fn iter(&self) -> Iter<'_, T> {
207 self.as_slice().iter()
208 }
209
210 #[inline]
212 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
213 self.as_mut().iter_mut()
214 }
215
216 pub fn map<F, O>(self, f: F) -> Array<O, U>
219 where
220 F: FnMut(T) -> O,
221 {
222 self.into_iter().map(f).collect()
223 }
224
225 #[inline]
227 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
228 where
229 N: ArraySize,
230 U: Add<N>,
231 Sum<U, N>: ArraySize,
232 {
233 let mut c = Array::uninit();
234 let (left, right) = c.split_at_mut(self.len());
235 for (val, dst) in self.into_iter().zip(left) {
236 dst.write(val);
237 }
238 for (val, dst) in other.into_iter().zip(right) {
239 dst.write(val);
240 }
241 unsafe { c.assume_init() }
243 }
244
245 #[inline]
249 pub fn split<N>(self) -> SplitResult<T, U, N>
250 where
251 U: Sub<N>,
252 N: ArraySize,
253 Diff<U, N>: ArraySize,
254 {
255 unsafe {
256 let array = ManuallyDrop::new(self);
257 let head = ptr::read(array.as_ptr().cast());
258 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
259 (head, tail)
260 }
261 }
262
263 #[inline]
265 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
266 where
267 U: Sub<N>,
268 N: ArraySize,
269 Diff<U, N>: ArraySize,
270 {
271 unsafe {
272 let array_ptr = self.as_ptr();
273 let head = &*array_ptr.cast();
274 let tail = &*array_ptr.add(N::USIZE).cast();
275 (head, tail)
276 }
277 }
278
279 #[inline]
281 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
282 where
283 U: Sub<N>,
284 N: ArraySize,
285 Diff<U, N>: ArraySize,
286 {
287 unsafe {
288 let array_ptr = self.as_mut_ptr();
289 let head = &mut *array_ptr.cast();
290 let tail = &mut *array_ptr.add(N::USIZE).cast();
291 (head, tail)
292 }
293 }
294
295 #[inline]
299 #[must_use]
300 pub const fn slice_as_array(slice: &[T]) -> Option<&Self> {
301 if slice.len() == U::USIZE {
302 unsafe { Some(&*slice.as_ptr().cast()) }
306 } else {
307 None
308 }
309 }
310
311 #[inline]
316 #[must_use]
317 pub const fn slice_as_mut_array(slice: &mut [T]) -> Option<&mut Self> {
318 if slice.len() == U::USIZE {
319 unsafe { Some(&mut *slice.as_mut_ptr().cast()) }
323 } else {
324 None
325 }
326 }
327
328 #[allow(clippy::arithmetic_side_effects)]
334 #[inline]
335 pub const fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
336 assert!(U::USIZE != 0, "chunk size must be non-zero");
337 let chunks_len = buf.len() / U::USIZE;
341 let tail_pos = U::USIZE * chunks_len;
342 let tail_len = buf.len() - tail_pos;
343 unsafe {
344 let ptr = buf.as_ptr();
345 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
346 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
347 (chunks, tail)
348 }
349 }
350
351 #[allow(clippy::arithmetic_side_effects)]
357 #[inline]
358 pub const fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
359 assert!(U::USIZE != 0, "chunk size must be non-zero");
360 let chunks_len = buf.len() / U::USIZE;
364 let tail_pos = U::USIZE * chunks_len;
365 let tail_len = buf.len() - tail_pos;
366 unsafe {
367 let ptr = buf.as_mut_ptr();
368 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
369 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
370 (chunks, tail)
371 }
372 }
373
374 #[inline]
379 pub const fn slice_as_flattened(slice: &[Self]) -> &[T] {
380 let len = slice
381 .len()
382 .checked_mul(U::USIZE)
383 .expect("slice len overflow");
384
385 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), len) }
388 }
389
390 #[inline]
395 pub const fn slice_as_flattened_mut(slice: &mut [Self]) -> &mut [T] {
396 let len = slice
397 .len()
398 .checked_mul(U::USIZE)
399 .expect("slice len overflow");
400
401 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) }
404 }
405}
406
407impl<T, U, V> Array<Array<T, U>, V>
408where
409 U: ArraySize,
410 V: ArraySize,
411{
412 pub const fn as_flattened(&self) -> &[T] {
443 Array::slice_as_flattened(self.as_slice())
444 }
445
446 pub const fn as_flattened_mut(&mut self) -> &mut [T] {
472 Array::slice_as_flattened_mut(self.as_mut_slice())
473 }
474}
475
476impl<T, U, const N: usize> Array<T, U>
478where
479 U: ArraySize<ArrayType<T> = [T; N]>,
480{
481 #[inline]
483 pub const fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
484 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
486 }
487
488 #[inline]
490 pub const fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
491 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
493 }
494
495 #[inline]
497 pub const fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
498 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
500 }
501
502 #[inline]
504 pub const fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
505 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
507 }
508}
509
510impl<T, U> Array<MaybeUninit<T>, U>
511where
512 U: ArraySize,
513{
514 #[must_use]
516 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
517 #[allow(clippy::uninit_assumed_init)]
526 Self(unsafe { MaybeUninit::uninit().assume_init() })
527 }
528
529 #[inline]
536 pub unsafe fn assume_init(self) -> Array<T, U> {
537 unsafe {
538 mem::transmute_copy(&self)
550 }
551 }
552}
553
554impl<T, U> AsRef<Array<T, U>> for Array<T, U>
555where
556 U: ArraySize,
557{
558 #[inline]
559 fn as_ref(&self) -> &Self {
560 self
561 }
562}
563
564impl<T, U> AsRef<[T]> for Array<T, U>
565where
566 U: ArraySize,
567{
568 #[inline]
569 fn as_ref(&self) -> &[T] {
570 self.0.as_ref()
571 }
572}
573
574impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
575where
576 U: ArraySize<ArrayType<T> = [T; N]>,
577{
578 #[inline]
579 fn as_ref(&self) -> &[T; N] {
580 &self.0
581 }
582}
583
584impl<T, U> AsMut<[T]> for Array<T, U>
585where
586 U: ArraySize,
587{
588 #[inline]
589 fn as_mut(&mut self) -> &mut [T] {
590 self.0.as_mut()
591 }
592}
593
594impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
595where
596 U: ArraySize<ArrayType<T> = [T; N]>,
597{
598 #[inline]
599 fn as_mut(&mut self) -> &mut [T; N] {
600 &mut self.0
601 }
602}
603
604impl<T, U> Borrow<[T]> for Array<T, U>
605where
606 U: ArraySize,
607{
608 #[inline]
609 fn borrow(&self) -> &[T] {
610 self.0.as_ref()
611 }
612}
613
614impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
615where
616 U: ArraySize<ArrayType<T> = [T; N]>,
617{
618 #[inline]
619 fn borrow(&self) -> &[T; N] {
620 &self.0
621 }
622}
623
624impl<T, U> BorrowMut<[T]> for Array<T, U>
625where
626 U: ArraySize,
627{
628 #[inline]
629 fn borrow_mut(&mut self) -> &mut [T] {
630 self.0.as_mut()
631 }
632}
633
634impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
635where
636 U: ArraySize<ArrayType<T> = [T; N]>,
637{
638 #[inline]
639 fn borrow_mut(&mut self) -> &mut [T; N] {
640 &mut self.0
641 }
642}
643
644impl<T, U> Clone for Array<T, U>
645where
646 T: Clone,
647 U: ArraySize,
648{
649 #[inline]
650 fn clone(&self) -> Self {
651 Self::from_fn(|n| self.0.as_ref()[n].clone())
652 }
653}
654
655impl<T, U> Copy for Array<T, U>
656where
657 T: Copy,
658 U: ArraySize,
659 U::ArrayType<T>: Copy,
660{
661}
662
663impl<T, U> Debug for Array<T, U>
664where
665 T: Debug,
666 U: ArraySize,
667{
668 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
669 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
670 }
671}
672
673impl<T, U> Default for Array<T, U>
674where
675 T: Default,
676 U: ArraySize,
677{
678 #[inline]
679 fn default() -> Self {
680 Self::from_fn(|_| Default::default())
681 }
682}
683
684impl<T, U> Deref for Array<T, U>
685where
686 U: ArraySize,
687{
688 type Target = [T];
689
690 #[inline]
691 fn deref(&self) -> &[T] {
692 self.0.as_ref()
693 }
694}
695
696impl<T, U> DerefMut for Array<T, U>
697where
698 U: ArraySize,
699{
700 #[inline]
701 fn deref_mut(&mut self) -> &mut [T] {
702 self.0.as_mut()
703 }
704}
705
706impl<T, U> Eq for Array<T, U>
707where
708 T: Eq,
709 U: ArraySize,
710{
711}
712
713impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
714where
715 U: ArraySize<ArrayType<T> = [T; N]>,
716{
717 #[inline]
718 fn from(arr: [T; N]) -> Array<T, U> {
719 Array(arr)
720 }
721}
722
723impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
724where
725 U: ArraySize<ArrayType<T> = [T; N]>,
726{
727 #[inline]
728 fn from(arr: Array<T, U>) -> [T; N] {
729 arr.0
730 }
731}
732
733impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
734where
735 U: ArraySize<ArrayType<T> = [T; N]>,
736{
737 #[inline]
738 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
739 unsafe { &*array_ref.as_ptr().cast() }
741 }
742}
743
744impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
745where
746 U: ArraySize<ArrayType<T> = [T; N]>,
747{
748 #[inline]
749 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
750 array_ref.as_ref()
751 }
752}
753
754impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
755where
756 U: ArraySize<ArrayType<T> = [T; N]>,
757{
758 #[inline]
759 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
760 unsafe { &mut *array_ref.as_mut_ptr().cast() }
762 }
763}
764
765impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
766where
767 U: ArraySize<ArrayType<T> = [T; N]>,
768{
769 #[inline]
770 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
771 array_ref.as_mut()
772 }
773}
774
775#[cfg(feature = "alloc")]
776impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
777where
778 U: ArraySize,
779{
780 #[inline]
781 fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
782 array.into_iter().collect()
783 }
784}
785
786#[cfg(feature = "alloc")]
787impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
788where
789 T: Clone,
790 U: ArraySize,
791{
792 #[inline]
793 fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
794 array.as_slice().into()
795 }
796}
797
798#[cfg(feature = "alloc")]
799impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
800where
801 U: ArraySize,
802{
803 #[inline]
804 fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
805 array.into_iter().collect()
806 }
807}
808
809#[cfg(feature = "alloc")]
810impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
811where
812 T: Clone,
813 U: ArraySize,
814{
815 #[inline]
816 fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
817 array.as_slice().into()
818 }
819}
820
821impl<T, U> Hash for Array<T, U>
822where
823 T: Hash,
824 U: ArraySize,
825{
826 #[inline]
827 fn hash<H: Hasher>(&self, state: &mut H) {
828 self.0.as_ref().hash(state);
829 }
830}
831
832impl<T, I, U> Index<I> for Array<T, U>
833where
834 [T]: Index<I>,
835 U: ArraySize,
836{
837 type Output = <[T] as Index<I>>::Output;
838
839 #[inline]
840 fn index(&self, index: I) -> &Self::Output {
841 Index::index(self.as_slice(), index)
842 }
843}
844
845impl<T, I, U> IndexMut<I> for Array<T, U>
846where
847 [T]: IndexMut<I>,
848 U: ArraySize,
849{
850 #[inline]
851 fn index_mut(&mut self, index: I) -> &mut Self::Output {
852 IndexMut::index_mut(self.as_mut_slice(), index)
853 }
854}
855
856impl<T, U> PartialEq for Array<T, U>
857where
858 T: PartialEq,
859 U: ArraySize,
860{
861 #[inline]
862 fn eq(&self, other: &Self) -> bool {
863 self.0.as_ref().eq(other.0.as_ref())
864 }
865}
866
867impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
868where
869 T: PartialEq,
870 U: ArraySize<ArrayType<T> = [T; N]>,
871{
872 #[inline]
873 fn eq(&self, other: &[T; N]) -> bool {
874 self.0.eq(other)
875 }
876}
877
878impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
879where
880 T: PartialEq,
881 U: ArraySize<ArrayType<T> = [T; N]>,
882{
883 #[inline]
884 fn eq(&self, other: &Array<T, U>) -> bool {
885 self.eq(&other.0)
886 }
887}
888
889impl<T, U> PartialOrd for Array<T, U>
890where
891 T: PartialOrd,
892 U: ArraySize,
893{
894 #[inline]
895 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
896 self.0.as_ref().partial_cmp(other.0.as_ref())
897 }
898}
899
900impl<T, U> Ord for Array<T, U>
901where
902 T: Ord,
903 U: ArraySize,
904{
905 #[inline]
906 fn cmp(&self, other: &Self) -> Ordering {
907 self.0.as_ref().cmp(other.0.as_ref())
908 }
909}
910
911unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
914
915unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
918
919impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
920where
921 U: ArraySize,
922{
923 type Error = TryFromSliceError;
924
925 #[inline]
926 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
927 check_slice_length::<T, U>(slice)?;
928
929 Ok(unsafe { &*slice.as_ptr().cast() })
932 }
933}
934
935impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
936where
937 U: ArraySize,
938{
939 type Error = TryFromSliceError;
940
941 #[inline]
942 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
943 check_slice_length::<T, U>(slice)?;
944
945 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
948 }
949}
950
951impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
952where
953 Self: Clone,
954 U: ArraySize,
955{
956 type Error = TryFromSliceError;
957
958 #[inline]
959 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
960 <&'a Self>::try_from(slice).cloned()
961 }
962}
963
964#[cfg(feature = "alloc")]
965impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
966where
967 Self: Clone,
968 U: ArraySize,
969{
970 type Error = TryFromSliceError;
971
972 #[inline]
973 fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
974 Self::try_from(&*b)
975 }
976}
977
978#[cfg(feature = "alloc")]
979impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
980where
981 Self: Clone,
982 U: ArraySize,
983{
984 type Error = TryFromSliceError;
985
986 #[inline]
987 fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
988 Self::try_from(&**b)
989 }
990}
991
992#[cfg(feature = "alloc")]
993impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
994where
995 Self: Clone,
996 U: ArraySize,
997{
998 type Error = TryFromSliceError;
999
1000 #[inline]
1001 fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
1002 Self::try_from(v.as_slice())
1003 }
1004}
1005
1006#[cfg(feature = "alloc")]
1007impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
1008where
1009 Self: Clone,
1010 U: ArraySize,
1011{
1012 type Error = TryFromSliceError;
1013
1014 #[inline]
1015 fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
1016 Self::try_from(v.as_slice())
1017 }
1018}
1019
1020impl<T, U> Array<T, U>
1022where
1023 U: ArraySize,
1024{
1025 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1031 #[inline]
1032 pub fn from_slice(slice: &[T]) -> &Self {
1033 slice.try_into().expect("slice length mismatch")
1034 }
1035
1036 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1042 #[inline]
1043 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
1044 slice.try_into().expect("slice length mismatch")
1045 }
1046
1047 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1053 #[inline]
1054 pub fn clone_from_slice(slice: &[T]) -> Self
1055 where
1056 Self: Clone,
1057 {
1058 slice.try_into().expect("slice length mismatch")
1059 }
1060}
1061
1062#[cfg(feature = "arbitrary")]
1063impl<'a, T, U> Arbitrary<'a> for Array<T, U>
1064where
1065 T: Arbitrary<'a>,
1066 U: ArraySize,
1067{
1068 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1069 Self::try_from_fn(|_n| Arbitrary::arbitrary(u))
1070 }
1071}
1072
1073#[cfg(feature = "bytemuck")]
1074unsafe impl<T, U> Pod for Array<T, U>
1075where
1076 T: Pod,
1077 U: ArraySize,
1078 U::ArrayType<T>: Copy,
1079{
1080}
1081
1082#[cfg(feature = "bytemuck")]
1083unsafe impl<T, U> Zeroable for Array<T, U>
1084where
1085 T: Zeroable,
1086 U: ArraySize,
1087{
1088}
1089
1090#[cfg(feature = "subtle")]
1091impl<T, U> ConditionallySelectable for Array<T, U>
1092where
1093 Self: Copy,
1094 T: ConditionallySelectable,
1095 U: ArraySize,
1096{
1097 #[inline]
1098 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
1099 let mut output = *a;
1100 output.conditional_assign(b, choice);
1101 output
1102 }
1103
1104 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
1105 for (a_i, b_i) in self.iter_mut().zip(other) {
1106 a_i.conditional_assign(b_i, choice);
1107 }
1108 }
1109}
1110
1111#[cfg(feature = "subtle")]
1112impl<T, U> ConstantTimeEq for Array<T, U>
1113where
1114 T: ConstantTimeEq,
1115 U: ArraySize,
1116{
1117 #[inline]
1118 fn ct_eq(&self, other: &Self) -> Choice {
1119 self.iter()
1120 .zip(other.iter())
1121 .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
1122 }
1123}
1124
1125#[cfg(feature = "zeroize")]
1126impl<T, U> Zeroize for Array<T, U>
1127where
1128 T: Zeroize,
1129 U: ArraySize,
1130{
1131 #[inline]
1132 fn zeroize(&mut self) {
1133 self.0.as_mut().iter_mut().zeroize();
1134 }
1135}
1136
1137#[cfg(feature = "zeroize")]
1138impl<T, U> ZeroizeOnDrop for Array<T, U>
1139where
1140 T: ZeroizeOnDrop,
1141 U: ArraySize,
1142{
1143}
1144
1145#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
1147fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
1148 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
1149
1150 if slice.len() != U::USIZE {
1151 <&[T; 1]>::try_from([].as_slice())?;
1153
1154 #[cfg(debug_assertions)]
1155 unreachable!();
1156 }
1157
1158 Ok(())
1159}