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 = "zeroize")]
138use zeroize::{Zeroize, ZeroizeOnDrop};
139
140#[cfg(feature = "zerocopy")]
141use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
142
143pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
145
146#[cfg_attr(
161 feature = "zerocopy",
162 derive(IntoBytes, FromBytes, Immutable, Unaligned, KnownLayout)
163)]
164#[repr(transparent)]
165pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
166
167type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
168type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
169type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
170
171impl<T, U> Array<T, U>
172where
173 U: ArraySize,
174{
175 #[inline]
177 pub const fn as_slice(&self) -> &[T] {
178 unsafe { slice::from_raw_parts(self.as_ptr(), U::USIZE) }
181 }
182
183 #[inline]
185 pub const fn as_mut_slice(&mut self) -> &mut [T] {
186 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), U::USIZE) }
189 }
190
191 pub const fn as_ptr(&self) -> *const T {
193 ptr::from_ref::<Self>(self).cast::<T>()
194 }
195
196 pub const fn as_mut_ptr(&mut self) -> *mut T {
198 ptr::from_mut::<Self>(self).cast::<T>()
199 }
200
201 #[inline]
203 pub fn iter(&self) -> Iter<'_, T> {
204 self.as_slice().iter()
205 }
206
207 #[inline]
209 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
210 self.as_mut().iter_mut()
211 }
212
213 pub fn map<F, O>(self, f: F) -> Array<O, U>
216 where
217 F: FnMut(T) -> O,
218 {
219 self.into_iter().map(f).collect()
220 }
221
222 #[inline]
224 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
225 where
226 N: ArraySize,
227 U: Add<N>,
228 Sum<U, N>: ArraySize,
229 {
230 let mut c = Array::uninit();
231 let (left, right) = c.split_at_mut(self.len());
232 for (val, dst) in self.into_iter().zip(left) {
233 dst.write(val);
234 }
235 for (val, dst) in other.into_iter().zip(right) {
236 dst.write(val);
237 }
238 unsafe { c.assume_init() }
240 }
241
242 #[inline]
246 pub fn split<N>(self) -> SplitResult<T, U, N>
247 where
248 U: Sub<N>,
249 N: ArraySize,
250 Diff<U, N>: ArraySize,
251 {
252 unsafe {
253 let array = ManuallyDrop::new(self);
254 let head = ptr::read(array.as_ptr().cast());
255 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
256 (head, tail)
257 }
258 }
259
260 #[inline]
262 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
263 where
264 U: Sub<N>,
265 N: ArraySize,
266 Diff<U, N>: ArraySize,
267 {
268 unsafe {
269 let array_ptr = self.as_ptr();
270 let head = &*array_ptr.cast();
271 let tail = &*array_ptr.add(N::USIZE).cast();
272 (head, tail)
273 }
274 }
275
276 #[inline]
278 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
279 where
280 U: Sub<N>,
281 N: ArraySize,
282 Diff<U, N>: ArraySize,
283 {
284 unsafe {
285 let array_ptr = self.as_mut_ptr();
286 let head = &mut *array_ptr.cast();
287 let tail = &mut *array_ptr.add(N::USIZE).cast();
288 (head, tail)
289 }
290 }
291
292 #[inline]
296 #[must_use]
297 pub const fn slice_as_array(slice: &[T]) -> Option<&Self> {
298 if slice.len() == U::USIZE {
299 unsafe { Some(&*slice.as_ptr().cast()) }
303 } else {
304 None
305 }
306 }
307
308 #[inline]
313 #[must_use]
314 pub const fn slice_as_mut_array(slice: &mut [T]) -> Option<&mut Self> {
315 if slice.len() == U::USIZE {
316 unsafe { Some(&mut *slice.as_mut_ptr().cast()) }
320 } else {
321 None
322 }
323 }
324
325 #[allow(clippy::arithmetic_side_effects)]
331 #[inline]
332 pub const fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
333 assert!(U::USIZE != 0, "chunk size must be non-zero");
334 let chunks_len = buf.len() / U::USIZE;
338 let tail_pos = U::USIZE * chunks_len;
339 let tail_len = buf.len() - tail_pos;
340 unsafe {
341 let ptr = buf.as_ptr();
342 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
343 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
344 (chunks, tail)
345 }
346 }
347
348 #[allow(clippy::arithmetic_side_effects)]
354 #[inline]
355 pub const fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
356 assert!(U::USIZE != 0, "chunk size must be non-zero");
357 let chunks_len = buf.len() / U::USIZE;
361 let tail_pos = U::USIZE * chunks_len;
362 let tail_len = buf.len() - tail_pos;
363 unsafe {
364 let ptr = buf.as_mut_ptr();
365 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
366 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
367 (chunks, tail)
368 }
369 }
370
371 #[inline]
376 pub const fn slice_as_flattened(slice: &[Self]) -> &[T] {
377 let len = slice
378 .len()
379 .checked_mul(U::USIZE)
380 .expect("slice len overflow");
381
382 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), len) }
385 }
386
387 #[inline]
392 pub const fn slice_as_flattened_mut(slice: &mut [Self]) -> &mut [T] {
393 let len = slice
394 .len()
395 .checked_mul(U::USIZE)
396 .expect("slice len overflow");
397
398 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) }
401 }
402}
403
404impl<T, U, V> Array<Array<T, U>, V>
405where
406 U: ArraySize,
407 V: ArraySize,
408{
409 pub const fn as_flattened(&self) -> &[T] {
440 Array::slice_as_flattened(self.as_slice())
441 }
442
443 pub const fn as_flattened_mut(&mut self) -> &mut [T] {
469 Array::slice_as_flattened_mut(self.as_mut_slice())
470 }
471}
472
473impl<T, U, const N: usize> Array<T, U>
475where
476 U: ArraySize<ArrayType<T> = [T; N]>,
477{
478 #[inline]
480 pub const fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
481 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
483 }
484
485 #[inline]
487 pub const fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
488 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
490 }
491
492 #[inline]
494 pub const fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
495 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
497 }
498
499 #[inline]
501 pub const fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
502 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
504 }
505}
506
507impl<T, U> Array<MaybeUninit<T>, U>
508where
509 U: ArraySize,
510{
511 #[must_use]
513 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
514 #[allow(clippy::uninit_assumed_init)]
523 Self(unsafe { MaybeUninit::uninit().assume_init() })
524 }
525
526 #[inline]
533 pub unsafe fn assume_init(self) -> Array<T, U> {
534 unsafe {
535 mem::transmute_copy(&self)
547 }
548 }
549}
550
551impl<T, U> AsRef<Array<T, U>> for Array<T, U>
552where
553 U: ArraySize,
554{
555 #[inline]
556 fn as_ref(&self) -> &Self {
557 self
558 }
559}
560
561impl<T, U> AsRef<[T]> for Array<T, U>
562where
563 U: ArraySize,
564{
565 #[inline]
566 fn as_ref(&self) -> &[T] {
567 self.0.as_ref()
568 }
569}
570
571impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
572where
573 U: ArraySize<ArrayType<T> = [T; N]>,
574{
575 #[inline]
576 fn as_ref(&self) -> &[T; N] {
577 &self.0
578 }
579}
580
581impl<T, U> AsMut<[T]> for Array<T, U>
582where
583 U: ArraySize,
584{
585 #[inline]
586 fn as_mut(&mut self) -> &mut [T] {
587 self.0.as_mut()
588 }
589}
590
591impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
592where
593 U: ArraySize<ArrayType<T> = [T; N]>,
594{
595 #[inline]
596 fn as_mut(&mut self) -> &mut [T; N] {
597 &mut self.0
598 }
599}
600
601impl<T, U> Borrow<[T]> for Array<T, U>
602where
603 U: ArraySize,
604{
605 #[inline]
606 fn borrow(&self) -> &[T] {
607 self.0.as_ref()
608 }
609}
610
611impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
612where
613 U: ArraySize<ArrayType<T> = [T; N]>,
614{
615 #[inline]
616 fn borrow(&self) -> &[T; N] {
617 &self.0
618 }
619}
620
621impl<T, U> BorrowMut<[T]> for Array<T, U>
622where
623 U: ArraySize,
624{
625 #[inline]
626 fn borrow_mut(&mut self) -> &mut [T] {
627 self.0.as_mut()
628 }
629}
630
631impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
632where
633 U: ArraySize<ArrayType<T> = [T; N]>,
634{
635 #[inline]
636 fn borrow_mut(&mut self) -> &mut [T; N] {
637 &mut self.0
638 }
639}
640
641impl<T, U> Clone for Array<T, U>
642where
643 T: Clone,
644 U: ArraySize,
645{
646 #[inline]
647 fn clone(&self) -> Self {
648 Self::from_fn(|n| self.0.as_ref()[n].clone())
649 }
650}
651
652impl<T, U> Copy for Array<T, U>
653where
654 T: Copy,
655 U: ArraySize,
656 U::ArrayType<T>: Copy,
657{
658}
659
660impl<T, U> Debug for Array<T, U>
661where
662 T: Debug,
663 U: ArraySize,
664{
665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
666 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
667 }
668}
669
670impl<T, U> Default for Array<T, U>
671where
672 T: Default,
673 U: ArraySize,
674{
675 #[inline]
676 fn default() -> Self {
677 Self::from_fn(|_| Default::default())
678 }
679}
680
681impl<T, U> Deref for Array<T, U>
682where
683 U: ArraySize,
684{
685 type Target = [T];
686
687 #[inline]
688 fn deref(&self) -> &[T] {
689 self.0.as_ref()
690 }
691}
692
693impl<T, U> DerefMut for Array<T, U>
694where
695 U: ArraySize,
696{
697 #[inline]
698 fn deref_mut(&mut self) -> &mut [T] {
699 self.0.as_mut()
700 }
701}
702
703impl<T, U> Eq for Array<T, U>
704where
705 T: Eq,
706 U: ArraySize,
707{
708}
709
710impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
711where
712 U: ArraySize<ArrayType<T> = [T; N]>,
713{
714 #[inline]
715 fn from(arr: [T; N]) -> Array<T, U> {
716 Array(arr)
717 }
718}
719
720impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
721where
722 U: ArraySize<ArrayType<T> = [T; N]>,
723{
724 #[inline]
725 fn from(arr: Array<T, U>) -> [T; N] {
726 arr.0
727 }
728}
729
730impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
731where
732 U: ArraySize<ArrayType<T> = [T; N]>,
733{
734 #[inline]
735 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
736 unsafe { &*array_ref.as_ptr().cast() }
738 }
739}
740
741impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
742where
743 U: ArraySize<ArrayType<T> = [T; N]>,
744{
745 #[inline]
746 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
747 array_ref.as_ref()
748 }
749}
750
751impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
752where
753 U: ArraySize<ArrayType<T> = [T; N]>,
754{
755 #[inline]
756 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
757 unsafe { &mut *array_ref.as_mut_ptr().cast() }
759 }
760}
761
762impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
763where
764 U: ArraySize<ArrayType<T> = [T; N]>,
765{
766 #[inline]
767 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
768 array_ref.as_mut()
769 }
770}
771
772#[cfg(feature = "alloc")]
773impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
774where
775 U: ArraySize,
776{
777 #[inline]
778 fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
779 array.into_iter().collect()
780 }
781}
782
783#[cfg(feature = "alloc")]
784impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
785where
786 T: Clone,
787 U: ArraySize,
788{
789 #[inline]
790 fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
791 array.as_slice().into()
792 }
793}
794
795#[cfg(feature = "alloc")]
796impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
797where
798 U: ArraySize,
799{
800 #[inline]
801 fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
802 array.into_iter().collect()
803 }
804}
805
806#[cfg(feature = "alloc")]
807impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
808where
809 T: Clone,
810 U: ArraySize,
811{
812 #[inline]
813 fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
814 array.as_slice().into()
815 }
816}
817
818impl<T, U> Hash for Array<T, U>
819where
820 T: Hash,
821 U: ArraySize,
822{
823 #[inline]
824 fn hash<H: Hasher>(&self, state: &mut H) {
825 self.0.as_ref().hash(state);
826 }
827}
828
829impl<T, I, U> Index<I> for Array<T, U>
830where
831 [T]: Index<I>,
832 U: ArraySize,
833{
834 type Output = <[T] as Index<I>>::Output;
835
836 #[inline]
837 fn index(&self, index: I) -> &Self::Output {
838 Index::index(self.as_slice(), index)
839 }
840}
841
842impl<T, I, U> IndexMut<I> for Array<T, U>
843where
844 [T]: IndexMut<I>,
845 U: ArraySize,
846{
847 #[inline]
848 fn index_mut(&mut self, index: I) -> &mut Self::Output {
849 IndexMut::index_mut(self.as_mut_slice(), index)
850 }
851}
852
853impl<T, U> PartialEq for Array<T, U>
854where
855 T: PartialEq,
856 U: ArraySize,
857{
858 #[inline]
859 fn eq(&self, other: &Self) -> bool {
860 self.0.as_ref().eq(other.0.as_ref())
861 }
862}
863
864impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
865where
866 T: PartialEq,
867 U: ArraySize<ArrayType<T> = [T; N]>,
868{
869 #[inline]
870 fn eq(&self, other: &[T; N]) -> bool {
871 self.0.eq(other)
872 }
873}
874
875impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
876where
877 T: PartialEq,
878 U: ArraySize<ArrayType<T> = [T; N]>,
879{
880 #[inline]
881 fn eq(&self, other: &Array<T, U>) -> bool {
882 self.eq(&other.0)
883 }
884}
885
886impl<T, U> PartialOrd for Array<T, U>
887where
888 T: PartialOrd,
889 U: ArraySize,
890{
891 #[inline]
892 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
893 self.0.as_ref().partial_cmp(other.0.as_ref())
894 }
895}
896
897impl<T, U> Ord for Array<T, U>
898where
899 T: Ord,
900 U: ArraySize,
901{
902 #[inline]
903 fn cmp(&self, other: &Self) -> Ordering {
904 self.0.as_ref().cmp(other.0.as_ref())
905 }
906}
907
908unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
911
912unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
915
916impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
917where
918 U: ArraySize,
919{
920 type Error = TryFromSliceError;
921
922 #[inline]
923 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
924 check_slice_length::<T, U>(slice)?;
925
926 Ok(unsafe { &*slice.as_ptr().cast() })
929 }
930}
931
932impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
933where
934 U: ArraySize,
935{
936 type Error = TryFromSliceError;
937
938 #[inline]
939 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
940 check_slice_length::<T, U>(slice)?;
941
942 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
945 }
946}
947
948impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
949where
950 Self: Clone,
951 U: ArraySize,
952{
953 type Error = TryFromSliceError;
954
955 #[inline]
956 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
957 <&'a Self>::try_from(slice).cloned()
958 }
959}
960
961#[cfg(feature = "alloc")]
962impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
963where
964 Self: Clone,
965 U: ArraySize,
966{
967 type Error = TryFromSliceError;
968
969 #[inline]
970 fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
971 Self::try_from(&*b)
972 }
973}
974
975#[cfg(feature = "alloc")]
976impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
977where
978 Self: Clone,
979 U: ArraySize,
980{
981 type Error = TryFromSliceError;
982
983 #[inline]
984 fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
985 Self::try_from(&**b)
986 }
987}
988
989#[cfg(feature = "alloc")]
990impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
991where
992 Self: Clone,
993 U: ArraySize,
994{
995 type Error = TryFromSliceError;
996
997 #[inline]
998 fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
999 Self::try_from(v.as_slice())
1000 }
1001}
1002
1003#[cfg(feature = "alloc")]
1004impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
1005where
1006 Self: Clone,
1007 U: ArraySize,
1008{
1009 type Error = TryFromSliceError;
1010
1011 #[inline]
1012 fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
1013 Self::try_from(v.as_slice())
1014 }
1015}
1016
1017impl<T, U> Array<T, U>
1019where
1020 U: ArraySize,
1021{
1022 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1028 #[inline]
1029 pub fn from_slice(slice: &[T]) -> &Self {
1030 slice.try_into().expect("slice length mismatch")
1031 }
1032
1033 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1039 #[inline]
1040 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
1041 slice.try_into().expect("slice length mismatch")
1042 }
1043
1044 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1050 #[inline]
1051 pub fn clone_from_slice(slice: &[T]) -> Self
1052 where
1053 Self: Clone,
1054 {
1055 slice.try_into().expect("slice length mismatch")
1056 }
1057}
1058
1059#[cfg(feature = "arbitrary")]
1060impl<'a, T, U> Arbitrary<'a> for Array<T, U>
1061where
1062 T: Arbitrary<'a>,
1063 U: ArraySize,
1064{
1065 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1066 Self::try_from_fn(|_n| Arbitrary::arbitrary(u))
1067 }
1068}
1069
1070#[cfg(feature = "bytemuck")]
1071unsafe impl<T, U> Pod for Array<T, U>
1072where
1073 T: Pod,
1074 U: ArraySize,
1075 U::ArrayType<T>: Copy,
1076{
1077}
1078
1079#[cfg(feature = "bytemuck")]
1080unsafe impl<T, U> Zeroable for Array<T, U>
1081where
1082 T: Zeroable,
1083 U: ArraySize,
1084{
1085}
1086
1087#[cfg(feature = "ctutils")]
1088impl<T, U> ctutils::CtAssign for Array<T, U>
1089where
1090 [T]: ctutils::CtAssign,
1091 U: ArraySize,
1092{
1093 #[inline]
1094 fn ct_assign(&mut self, other: &Self, choice: ctutils::Choice) {
1095 self.as_mut_slice().ct_assign(other.as_slice(), choice);
1096 }
1097}
1098
1099#[cfg(feature = "ctutils")]
1100impl<T, U> ctutils::CtSelect for Array<T, U>
1101where
1102 U: ArraySize,
1103 U::ArrayType<T>: ctutils::CtSelect,
1104{
1105 #[inline]
1106 fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
1107 Self(self.0.ct_select(&other.0, choice))
1108 }
1109}
1110
1111#[cfg(feature = "ctutils")]
1112impl<T, U> ctutils::CtEq for Array<T, U>
1113where
1114 U: ArraySize,
1115 U::ArrayType<T>: ctutils::CtEq,
1116{
1117 #[inline]
1118 fn ct_eq(&self, other: &Self) -> ctutils::Choice {
1119 self.0.ct_eq(&other.0)
1120 }
1121}
1122
1123#[cfg(feature = "subtle")]
1124impl<T, U> subtle::ConditionallySelectable for Array<T, U>
1125where
1126 Self: Copy,
1127 T: subtle::ConditionallySelectable,
1128 U: ArraySize,
1129{
1130 #[inline]
1131 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
1132 let mut output = *a;
1133 output.conditional_assign(b, choice);
1134 output
1135 }
1136
1137 fn conditional_assign(&mut self, other: &Self, choice: subtle::Choice) {
1138 for (a_i, b_i) in self.iter_mut().zip(other) {
1139 a_i.conditional_assign(b_i, choice);
1140 }
1141 }
1142}
1143
1144#[cfg(feature = "subtle")]
1145impl<T, U> subtle::ConstantTimeEq for Array<T, U>
1146where
1147 T: subtle::ConstantTimeEq,
1148 U: ArraySize,
1149{
1150 #[inline]
1151 fn ct_eq(&self, other: &Self) -> subtle::Choice {
1152 self.iter()
1153 .zip(other.iter())
1154 .fold(subtle::Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
1155 }
1156}
1157
1158#[cfg(feature = "zeroize")]
1159impl<T, U> Zeroize for Array<T, U>
1160where
1161 T: Zeroize,
1162 U: ArraySize,
1163{
1164 #[inline]
1165 fn zeroize(&mut self) {
1166 self.0.as_mut().iter_mut().zeroize();
1167 }
1168}
1169
1170#[cfg(feature = "zeroize")]
1171impl<T, U> ZeroizeOnDrop for Array<T, U>
1172where
1173 T: ZeroizeOnDrop,
1174 U: ArraySize,
1175{
1176}
1177
1178#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
1180fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
1181 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
1182
1183 if slice.len() != U::USIZE {
1184 <&[T; 1]>::try_from([].as_slice())?;
1186
1187 #[cfg(debug_assertions)]
1188 unreachable!();
1189 }
1190
1191 Ok(())
1192}