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
31pub mod sizes;
109
110mod from_fn;
111mod iter;
112mod traits;
113
114#[cfg(feature = "serde")]
115mod serde;
116
117pub use crate::{iter::TryFromIteratorError, traits::*};
118pub use typenum;
119
120use core::{
121 array::TryFromSliceError,
122 borrow::{Borrow, BorrowMut},
123 cmp::Ordering,
124 fmt::{self, Debug},
125 hash::{Hash, Hasher},
126 mem::{self, ManuallyDrop, MaybeUninit},
127 ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
128 ptr,
129 slice::{self, Iter, IterMut},
130};
131use typenum::{Diff, Sum};
132
133#[cfg(feature = "bytemuck")]
134use bytemuck::{Pod, Zeroable};
135
136#[cfg(feature = "subtle")]
137use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
138
139#[cfg(feature = "zeroize")]
140use zeroize::{Zeroize, ZeroizeOnDrop};
141
142pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
144
145#[repr(transparent)]
186pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
187
188type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
189type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
190type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
191
192impl<T, U> Array<T, U>
193where
194 U: ArraySize,
195{
196 #[inline]
198 pub fn as_slice(&self) -> &[T] {
199 self.0.as_ref()
200 }
201
202 #[inline]
204 pub fn as_mut_slice(&mut self) -> &mut [T] {
205 self.0.as_mut()
206 }
207
208 #[inline]
210 pub fn iter(&self) -> Iter<'_, T> {
211 self.as_slice().iter()
212 }
213
214 #[inline]
216 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
217 self.as_mut().iter_mut()
218 }
219
220 pub fn map<F, O>(self, f: F) -> Array<O, U>
223 where
224 F: FnMut(T) -> O,
225 {
226 self.into_iter().map(f).collect()
227 }
228
229 #[inline]
231 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
232 where
233 N: ArraySize,
234 U: Add<N>,
235 Sum<U, N>: ArraySize,
236 {
237 let mut c = Array::uninit();
238 let (left, right) = c.split_at_mut(self.len());
239 for (val, dst) in self.into_iter().zip(left) {
240 dst.write(val);
241 }
242 for (val, dst) in other.into_iter().zip(right) {
243 dst.write(val);
244 }
245 unsafe { c.assume_init() }
247 }
248
249 #[inline]
253 pub fn split<N>(self) -> SplitResult<T, U, N>
254 where
255 U: Sub<N>,
256 N: ArraySize,
257 Diff<U, N>: ArraySize,
258 {
259 unsafe {
260 let array = ManuallyDrop::new(self);
261 let head = ptr::read(array.as_ptr().cast());
262 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
263 (head, tail)
264 }
265 }
266
267 #[inline]
269 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
270 where
271 U: Sub<N>,
272 N: ArraySize,
273 Diff<U, N>: ArraySize,
274 {
275 unsafe {
276 let array_ptr = self.as_ptr();
277 let head = &*array_ptr.cast();
278 let tail = &*array_ptr.add(N::USIZE).cast();
279 (head, tail)
280 }
281 }
282
283 #[inline]
285 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
286 where
287 U: Sub<N>,
288 N: ArraySize,
289 Diff<U, N>: ArraySize,
290 {
291 unsafe {
292 let array_ptr = self.as_mut_ptr();
293 let head = &mut *array_ptr.cast();
294 let tail = &mut *array_ptr.add(N::USIZE).cast();
295 (head, tail)
296 }
297 }
298
299 #[allow(clippy::arithmetic_side_effects)]
305 #[inline]
306 pub fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
307 assert_ne!(U::USIZE, 0, "chunk size must be non-zero");
308 let chunks_len = buf.len() / U::USIZE;
312 let tail_pos = U::USIZE * chunks_len;
313 let tail_len = buf.len() - tail_pos;
314 unsafe {
315 let ptr = buf.as_ptr();
316 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
317 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
318 (chunks, tail)
319 }
320 }
321
322 #[allow(clippy::arithmetic_side_effects)]
328 #[inline]
329 pub fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
330 assert_ne!(U::USIZE, 0, "chunk size must be non-zero");
331 let chunks_len = buf.len() / U::USIZE;
335 let tail_pos = U::USIZE * chunks_len;
336 let tail_len = buf.len() - tail_pos;
337 unsafe {
338 let ptr = buf.as_mut_ptr();
339 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
340 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
341 (chunks, tail)
342 }
343 }
344
345 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
351 #[inline]
352 pub fn from_slice(slice: &[T]) -> &Self {
353 slice.try_into().expect("slice length mismatch")
354 }
355
356 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
362 #[inline]
363 pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
364 slice.try_into().expect("slice length mismatch")
365 }
366
367 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
373 #[inline]
374 pub fn clone_from_slice(slice: &[T]) -> Self
375 where
376 Self: Clone,
377 {
378 slice.try_into().expect("slice length mismatch")
379 }
380}
381
382impl<T, U, const N: usize> Array<T, U>
384where
385 U: ArraySize<ArrayType<T> = [T; N]>,
386{
387 #[inline]
389 pub fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
390 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
392 }
393
394 #[inline]
396 pub fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
397 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
399 }
400
401 #[inline]
403 pub fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
404 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
406 }
407
408 #[inline]
410 pub fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
411 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
413 }
414}
415
416impl<T, U> Array<MaybeUninit<T>, U>
417where
418 U: ArraySize,
419{
420 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
422 #[allow(clippy::uninit_assumed_init)]
431 Self(unsafe { MaybeUninit::uninit().assume_init() })
432 }
433
434 #[inline]
441 pub unsafe fn assume_init(self) -> Array<T, U> {
442 unsafe {
443 mem::transmute_copy(&self)
455 }
456 }
457}
458
459impl<T, U> AsRef<Array<T, U>> for Array<T, U>
460where
461 U: ArraySize,
462{
463 #[inline]
464 fn as_ref(&self) -> &Self {
465 self
466 }
467}
468
469impl<T, U> AsRef<[T]> for Array<T, U>
470where
471 U: ArraySize,
472{
473 #[inline]
474 fn as_ref(&self) -> &[T] {
475 self.0.as_ref()
476 }
477}
478
479impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
480where
481 U: ArraySize<ArrayType<T> = [T; N]>,
482{
483 #[inline]
484 fn as_ref(&self) -> &[T; N] {
485 &self.0
486 }
487}
488
489impl<T, U, const N: usize> AsRef<Array<T, U>> for [T; N]
490where
491 U: ArraySize<ArrayType<T> = [T; N]>,
492{
493 #[inline]
494 fn as_ref(&self) -> &Array<T, U> {
495 unsafe { &*self.as_ptr().cast() }
497 }
498}
499
500impl<T, U> AsMut<[T]> for Array<T, U>
501where
502 U: ArraySize,
503{
504 #[inline]
505 fn as_mut(&mut self) -> &mut [T] {
506 self.0.as_mut()
507 }
508}
509
510impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
511where
512 U: ArraySize<ArrayType<T> = [T; N]>,
513{
514 #[inline]
515 fn as_mut(&mut self) -> &mut [T; N] {
516 &mut self.0
517 }
518}
519
520impl<T, U, const N: usize> AsMut<Array<T, U>> for [T; N]
521where
522 U: ArraySize<ArrayType<T> = [T; N]>,
523{
524 #[inline]
525 fn as_mut(&mut self) -> &mut Array<T, U> {
526 unsafe { &mut *self.as_mut_ptr().cast() }
528 }
529}
530
531impl<T, U> Borrow<[T]> for Array<T, U>
532where
533 U: ArraySize,
534{
535 #[inline]
536 fn borrow(&self) -> &[T] {
537 self.0.as_ref()
538 }
539}
540
541impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
542where
543 U: ArraySize<ArrayType<T> = [T; N]>,
544{
545 #[inline]
546 fn borrow(&self) -> &[T; N] {
547 &self.0
548 }
549}
550
551impl<T, U> BorrowMut<[T]> for Array<T, U>
552where
553 U: ArraySize,
554{
555 #[inline]
556 fn borrow_mut(&mut self) -> &mut [T] {
557 self.0.as_mut()
558 }
559}
560
561impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
562where
563 U: ArraySize<ArrayType<T> = [T; N]>,
564{
565 #[inline]
566 fn borrow_mut(&mut self) -> &mut [T; N] {
567 &mut self.0
568 }
569}
570
571impl<T, U> Clone for Array<T, U>
572where
573 T: Clone,
574 U: ArraySize,
575{
576 #[inline]
577 fn clone(&self) -> Self {
578 Self::from_fn(|n| self.0.as_ref()[n].clone())
579 }
580}
581
582impl<T, U> Copy for Array<T, U>
583where
584 T: Copy,
585 U: ArraySize,
586 U::ArrayType<T>: Copy,
587{
588}
589
590impl<T, U> Debug for Array<T, U>
591where
592 T: Debug,
593 U: ArraySize,
594{
595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
596 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
597 }
598}
599
600impl<T, U> Default for Array<T, U>
601where
602 T: Default,
603 U: ArraySize,
604{
605 #[inline]
606 fn default() -> Self {
607 Self::from_fn(|_| Default::default())
608 }
609}
610
611impl<T, U> Deref for Array<T, U>
612where
613 U: ArraySize,
614{
615 type Target = [T];
616
617 #[inline]
618 fn deref(&self) -> &[T] {
619 self.0.as_ref()
620 }
621}
622
623impl<T, U> DerefMut for Array<T, U>
624where
625 U: ArraySize,
626{
627 #[inline]
628 fn deref_mut(&mut self) -> &mut [T] {
629 self.0.as_mut()
630 }
631}
632
633impl<T, U> Eq for Array<T, U>
634where
635 T: Eq,
636 U: ArraySize,
637{
638}
639
640impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
641where
642 U: ArraySize<ArrayType<T> = [T; N]>,
643{
644 #[inline]
645 fn from(arr: [T; N]) -> Array<T, U> {
646 Array(arr)
647 }
648}
649
650impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
651where
652 U: ArraySize<ArrayType<T> = [T; N]>,
653{
654 #[inline]
655 fn from(arr: Array<T, U>) -> [T; N] {
656 arr.0
657 }
658}
659
660impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
661where
662 U: ArraySize<ArrayType<T> = [T; N]>,
663{
664 #[inline]
665 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
666 array_ref.as_ref()
667 }
668}
669
670impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
671where
672 U: ArraySize<ArrayType<T> = [T; N]>,
673{
674 #[inline]
675 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
676 array_ref.as_ref()
677 }
678}
679
680impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
681where
682 U: ArraySize<ArrayType<T> = [T; N]>,
683{
684 #[inline]
685 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
686 array_ref.as_mut()
687 }
688}
689
690impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
691where
692 U: ArraySize<ArrayType<T> = [T; N]>,
693{
694 #[inline]
695 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
696 array_ref.as_mut()
697 }
698}
699
700impl<T, U> Hash for Array<T, U>
701where
702 T: Hash,
703 U: ArraySize,
704{
705 #[inline]
706 fn hash<H: Hasher>(&self, state: &mut H) {
707 self.0.as_ref().hash(state);
708 }
709}
710
711impl<T, I, U> Index<I> for Array<T, U>
712where
713 [T]: Index<I>,
714 U: ArraySize,
715{
716 type Output = <[T] as Index<I>>::Output;
717
718 #[inline]
719 fn index(&self, index: I) -> &Self::Output {
720 Index::index(self.as_slice(), index)
721 }
722}
723
724impl<T, I, U> IndexMut<I> for Array<T, U>
725where
726 [T]: IndexMut<I>,
727 U: ArraySize,
728{
729 #[inline]
730 fn index_mut(&mut self, index: I) -> &mut Self::Output {
731 IndexMut::index_mut(self.as_mut_slice(), index)
732 }
733}
734
735impl<T, U> PartialEq for Array<T, U>
736where
737 T: PartialEq,
738 U: ArraySize,
739{
740 #[inline]
741 fn eq(&self, other: &Self) -> bool {
742 self.0.as_ref().eq(other.0.as_ref())
743 }
744}
745
746impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
747where
748 T: PartialEq,
749 U: ArraySize<ArrayType<T> = [T; N]>,
750{
751 #[inline]
752 fn eq(&self, other: &[T; N]) -> bool {
753 self.0.eq(other)
754 }
755}
756
757impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
758where
759 T: PartialEq,
760 U: ArraySize<ArrayType<T> = [T; N]>,
761{
762 #[inline]
763 fn eq(&self, other: &Array<T, U>) -> bool {
764 self.eq(&other.0)
765 }
766}
767
768impl<T, U> PartialOrd for Array<T, U>
769where
770 T: PartialOrd,
771 U: ArraySize,
772{
773 #[inline]
774 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
775 self.0.as_ref().partial_cmp(other.0.as_ref())
776 }
777}
778
779impl<T, U> Ord for Array<T, U>
780where
781 T: Ord,
782 U: ArraySize,
783{
784 #[inline]
785 fn cmp(&self, other: &Self) -> Ordering {
786 self.0.as_ref().cmp(other.0.as_ref())
787 }
788}
789
790unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
793
794unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
797
798impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
799where
800 Self: Clone,
801 U: ArraySize,
802{
803 type Error = TryFromSliceError;
804
805 #[inline]
806 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
807 <&'a Self>::try_from(slice).cloned()
808 }
809}
810
811impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
812where
813 U: ArraySize,
814{
815 type Error = TryFromSliceError;
816
817 #[inline]
818 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
819 check_slice_length::<T, U>(slice)?;
820
821 Ok(unsafe { &*slice.as_ptr().cast() })
824 }
825}
826
827impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
828where
829 U: ArraySize,
830{
831 type Error = TryFromSliceError;
832
833 #[inline]
834 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
835 check_slice_length::<T, U>(slice)?;
836
837 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
840 }
841}
842
843#[cfg(feature = "bytemuck")]
844unsafe impl<T, U> Pod for Array<T, U>
845where
846 T: Pod,
847 U: ArraySize,
848 U::ArrayType<T>: Copy,
849{
850}
851
852#[cfg(feature = "bytemuck")]
853unsafe impl<T, U> Zeroable for Array<T, U>
854where
855 T: Zeroable,
856 U: ArraySize,
857{
858}
859
860#[cfg(feature = "subtle")]
861impl<T, U> ConditionallySelectable for Array<T, U>
862where
863 Self: Copy,
864 T: ConditionallySelectable,
865 U: ArraySize,
866{
867 #[inline]
868 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
869 let mut output = *a;
870 output.conditional_assign(b, choice);
871 output
872 }
873
874 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
875 for (a_i, b_i) in self.iter_mut().zip(other) {
876 a_i.conditional_assign(b_i, choice)
877 }
878 }
879}
880
881#[cfg(feature = "subtle")]
882impl<T, U> ConstantTimeEq for Array<T, U>
883where
884 T: ConstantTimeEq,
885 U: ArraySize,
886{
887 #[inline]
888 fn ct_eq(&self, other: &Self) -> Choice {
889 self.iter()
890 .zip(other.iter())
891 .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
892 }
893}
894
895#[cfg(feature = "zeroize")]
896impl<T, U> Zeroize for Array<T, U>
897where
898 T: Zeroize,
899 U: ArraySize,
900{
901 #[inline]
902 fn zeroize(&mut self) {
903 self.0.as_mut().iter_mut().zeroize()
904 }
905}
906
907#[cfg(feature = "zeroize")]
908impl<T, U> ZeroizeOnDrop for Array<T, U>
909where
910 T: ZeroizeOnDrop,
911 U: ArraySize,
912{
913}
914
915#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
917fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
918 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
919
920 if slice.len() != U::USIZE {
921 <&[T; 1]>::try_from([].as_slice())?;
923
924 #[cfg(debug_assertions)]
925 unreachable!();
926 }
927
928 Ok(())
929}