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 fn as_slice(&self) -> &[T] {
188 self.0.as_ref()
189 }
190
191 #[inline]
193 pub fn as_mut_slice(&mut self) -> &mut [T] {
194 self.0.as_mut()
195 }
196
197 #[inline]
199 pub fn iter(&self) -> Iter<'_, T> {
200 self.as_slice().iter()
201 }
202
203 #[inline]
205 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
206 self.as_mut().iter_mut()
207 }
208
209 pub fn map<F, O>(self, f: F) -> Array<O, U>
212 where
213 F: FnMut(T) -> O,
214 {
215 self.into_iter().map(f).collect()
216 }
217
218 #[inline]
220 pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
221 where
222 N: ArraySize,
223 U: Add<N>,
224 Sum<U, N>: ArraySize,
225 {
226 let mut c = Array::uninit();
227 let (left, right) = c.split_at_mut(self.len());
228 for (val, dst) in self.into_iter().zip(left) {
229 dst.write(val);
230 }
231 for (val, dst) in other.into_iter().zip(right) {
232 dst.write(val);
233 }
234 unsafe { c.assume_init() }
236 }
237
238 #[inline]
242 pub fn split<N>(self) -> SplitResult<T, U, N>
243 where
244 U: Sub<N>,
245 N: ArraySize,
246 Diff<U, N>: ArraySize,
247 {
248 unsafe {
249 let array = ManuallyDrop::new(self);
250 let head = ptr::read(array.as_ptr().cast());
251 let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
252 (head, tail)
253 }
254 }
255
256 #[inline]
258 pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
259 where
260 U: Sub<N>,
261 N: ArraySize,
262 Diff<U, N>: ArraySize,
263 {
264 unsafe {
265 let array_ptr = self.as_ptr();
266 let head = &*array_ptr.cast();
267 let tail = &*array_ptr.add(N::USIZE).cast();
268 (head, tail)
269 }
270 }
271
272 #[inline]
274 pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, 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_mut_ptr();
282 let head = &mut *array_ptr.cast();
283 let tail = &mut *array_ptr.add(N::USIZE).cast();
284 (head, tail)
285 }
286 }
287
288 #[allow(clippy::arithmetic_side_effects)]
294 #[inline]
295 pub const fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
296 assert!(U::USIZE != 0, "chunk size must be non-zero");
297 let chunks_len = buf.len() / U::USIZE;
301 let tail_pos = U::USIZE * chunks_len;
302 let tail_len = buf.len() - tail_pos;
303 unsafe {
304 let ptr = buf.as_ptr();
305 let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
306 let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
307 (chunks, tail)
308 }
309 }
310
311 #[allow(clippy::arithmetic_side_effects)]
317 #[inline]
318 pub const fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
319 assert!(U::USIZE != 0, "chunk size must be non-zero");
320 let chunks_len = buf.len() / U::USIZE;
324 let tail_pos = U::USIZE * chunks_len;
325 let tail_len = buf.len() - tail_pos;
326 unsafe {
327 let ptr = buf.as_mut_ptr();
328 let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
329 let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
330 (chunks, tail)
331 }
332 }
333
334 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
340 #[inline]
341 pub fn from_slice(slice: &[T]) -> &Self {
342 slice.try_into().expect("slice length mismatch")
343 }
344
345 #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
351 #[inline]
352 pub fn from_mut_slice(slice: &mut [T]) -> &mut 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 clone_from_slice(slice: &[T]) -> Self
364 where
365 Self: Clone,
366 {
367 slice.try_into().expect("slice length mismatch")
368 }
369}
370
371impl<T, U, const N: usize> Array<T, U>
373where
374 U: ArraySize<ArrayType<T> = [T; N]>,
375{
376 #[inline]
378 pub const fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
379 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
381 }
382
383 #[inline]
385 pub const fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
386 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
388 }
389
390 #[inline]
392 pub const fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
393 unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
395 }
396
397 #[inline]
399 pub const fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
400 unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
402 }
403
404 #[inline]
406 pub fn slice_as_flattened(slice: &[Self]) -> &[T] {
407 Self::cast_slice_to_core(slice).as_flattened()
408 }
409
410 #[inline]
412 pub fn slice_as_flattened_mut(slice: &mut [Self]) -> &mut [T] {
413 Self::cast_slice_to_core_mut(slice).as_flattened_mut()
414 }
415}
416
417impl<T, U> Array<MaybeUninit<T>, U>
418where
419 U: ArraySize,
420{
421 pub const fn uninit() -> Array<MaybeUninit<T>, U> {
423 #[allow(clippy::uninit_assumed_init)]
432 Self(unsafe { MaybeUninit::uninit().assume_init() })
433 }
434
435 #[inline]
442 pub unsafe fn assume_init(self) -> Array<T, U> {
443 unsafe {
444 mem::transmute_copy(&self)
456 }
457 }
458}
459
460impl<T, U> AsRef<Array<T, U>> for Array<T, U>
461where
462 U: ArraySize,
463{
464 #[inline]
465 fn as_ref(&self) -> &Self {
466 self
467 }
468}
469
470impl<T, U> AsRef<[T]> for Array<T, U>
471where
472 U: ArraySize,
473{
474 #[inline]
475 fn as_ref(&self) -> &[T] {
476 self.0.as_ref()
477 }
478}
479
480impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
481where
482 U: ArraySize<ArrayType<T> = [T; N]>,
483{
484 #[inline]
485 fn as_ref(&self) -> &[T; N] {
486 &self.0
487 }
488}
489
490impl<T, U> AsMut<[T]> for Array<T, U>
491where
492 U: ArraySize,
493{
494 #[inline]
495 fn as_mut(&mut self) -> &mut [T] {
496 self.0.as_mut()
497 }
498}
499
500impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
501where
502 U: ArraySize<ArrayType<T> = [T; N]>,
503{
504 #[inline]
505 fn as_mut(&mut self) -> &mut [T; N] {
506 &mut self.0
507 }
508}
509
510impl<T, U> Borrow<[T]> for Array<T, U>
511where
512 U: ArraySize,
513{
514 #[inline]
515 fn borrow(&self) -> &[T] {
516 self.0.as_ref()
517 }
518}
519
520impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
521where
522 U: ArraySize<ArrayType<T> = [T; N]>,
523{
524 #[inline]
525 fn borrow(&self) -> &[T; N] {
526 &self.0
527 }
528}
529
530impl<T, U> BorrowMut<[T]> for Array<T, U>
531where
532 U: ArraySize,
533{
534 #[inline]
535 fn borrow_mut(&mut self) -> &mut [T] {
536 self.0.as_mut()
537 }
538}
539
540impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
541where
542 U: ArraySize<ArrayType<T> = [T; N]>,
543{
544 #[inline]
545 fn borrow_mut(&mut self) -> &mut [T; N] {
546 &mut self.0
547 }
548}
549
550impl<T, U> Clone for Array<T, U>
551where
552 T: Clone,
553 U: ArraySize,
554{
555 #[inline]
556 fn clone(&self) -> Self {
557 Self::from_fn(|n| self.0.as_ref()[n].clone())
558 }
559}
560
561impl<T, U> Copy for Array<T, U>
562where
563 T: Copy,
564 U: ArraySize,
565 U::ArrayType<T>: Copy,
566{
567}
568
569impl<T, U> Debug for Array<T, U>
570where
571 T: Debug,
572 U: ArraySize,
573{
574 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575 f.debug_tuple("Array").field(&self.0.as_ref()).finish()
576 }
577}
578
579impl<T, U> Default for Array<T, U>
580where
581 T: Default,
582 U: ArraySize,
583{
584 #[inline]
585 fn default() -> Self {
586 Self::from_fn(|_| Default::default())
587 }
588}
589
590impl<T, U> Deref for Array<T, U>
591where
592 U: ArraySize,
593{
594 type Target = [T];
595
596 #[inline]
597 fn deref(&self) -> &[T] {
598 self.0.as_ref()
599 }
600}
601
602impl<T, U> DerefMut for Array<T, U>
603where
604 U: ArraySize,
605{
606 #[inline]
607 fn deref_mut(&mut self) -> &mut [T] {
608 self.0.as_mut()
609 }
610}
611
612impl<T, U> Eq for Array<T, U>
613where
614 T: Eq,
615 U: ArraySize,
616{
617}
618
619impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
620where
621 U: ArraySize<ArrayType<T> = [T; N]>,
622{
623 #[inline]
624 fn from(arr: [T; N]) -> Array<T, U> {
625 Array(arr)
626 }
627}
628
629impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
630where
631 U: ArraySize<ArrayType<T> = [T; N]>,
632{
633 #[inline]
634 fn from(arr: Array<T, U>) -> [T; N] {
635 arr.0
636 }
637}
638
639impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
640where
641 U: ArraySize<ArrayType<T> = [T; N]>,
642{
643 #[inline]
644 fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
645 unsafe { &*array_ref.as_ptr().cast() }
647 }
648}
649
650impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
651where
652 U: ArraySize<ArrayType<T> = [T; N]>,
653{
654 #[inline]
655 fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
656 array_ref.as_ref()
657 }
658}
659
660impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
661where
662 U: ArraySize<ArrayType<T> = [T; N]>,
663{
664 #[inline]
665 fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
666 unsafe { &mut *array_ref.as_mut_ptr().cast() }
668 }
669}
670
671impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
672where
673 U: ArraySize<ArrayType<T> = [T; N]>,
674{
675 #[inline]
676 fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
677 array_ref.as_mut()
678 }
679}
680
681#[cfg(feature = "alloc")]
682impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
683where
684 U: ArraySize,
685{
686 #[inline]
687 fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
688 array.into_iter().collect()
689 }
690}
691
692#[cfg(feature = "alloc")]
693impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
694where
695 T: Clone,
696 U: ArraySize,
697{
698 #[inline]
699 fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
700 array.as_slice().into()
701 }
702}
703
704#[cfg(feature = "alloc")]
705impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
706where
707 U: ArraySize,
708{
709 #[inline]
710 fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
711 array.into_iter().collect()
712 }
713}
714
715#[cfg(feature = "alloc")]
716impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
717where
718 T: Clone,
719 U: ArraySize,
720{
721 #[inline]
722 fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
723 array.as_slice().into()
724 }
725}
726
727impl<T, U> Hash for Array<T, U>
728where
729 T: Hash,
730 U: ArraySize,
731{
732 #[inline]
733 fn hash<H: Hasher>(&self, state: &mut H) {
734 self.0.as_ref().hash(state);
735 }
736}
737
738impl<T, I, U> Index<I> for Array<T, U>
739where
740 [T]: Index<I>,
741 U: ArraySize,
742{
743 type Output = <[T] as Index<I>>::Output;
744
745 #[inline]
746 fn index(&self, index: I) -> &Self::Output {
747 Index::index(self.as_slice(), index)
748 }
749}
750
751impl<T, I, U> IndexMut<I> for Array<T, U>
752where
753 [T]: IndexMut<I>,
754 U: ArraySize,
755{
756 #[inline]
757 fn index_mut(&mut self, index: I) -> &mut Self::Output {
758 IndexMut::index_mut(self.as_mut_slice(), index)
759 }
760}
761
762impl<T, U> PartialEq for Array<T, U>
763where
764 T: PartialEq,
765 U: ArraySize,
766{
767 #[inline]
768 fn eq(&self, other: &Self) -> bool {
769 self.0.as_ref().eq(other.0.as_ref())
770 }
771}
772
773impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
774where
775 T: PartialEq,
776 U: ArraySize<ArrayType<T> = [T; N]>,
777{
778 #[inline]
779 fn eq(&self, other: &[T; N]) -> bool {
780 self.0.eq(other)
781 }
782}
783
784impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
785where
786 T: PartialEq,
787 U: ArraySize<ArrayType<T> = [T; N]>,
788{
789 #[inline]
790 fn eq(&self, other: &Array<T, U>) -> bool {
791 self.eq(&other.0)
792 }
793}
794
795impl<T, U> PartialOrd for Array<T, U>
796where
797 T: PartialOrd,
798 U: ArraySize,
799{
800 #[inline]
801 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
802 self.0.as_ref().partial_cmp(other.0.as_ref())
803 }
804}
805
806impl<T, U> Ord for Array<T, U>
807where
808 T: Ord,
809 U: ArraySize,
810{
811 #[inline]
812 fn cmp(&self, other: &Self) -> Ordering {
813 self.0.as_ref().cmp(other.0.as_ref())
814 }
815}
816
817unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
820
821unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
824
825impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
826where
827 Self: Clone,
828 U: ArraySize,
829{
830 type Error = TryFromSliceError;
831
832 #[inline]
833 fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
834 <&'a Self>::try_from(slice).cloned()
835 }
836}
837
838#[cfg(feature = "alloc")]
839impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
840where
841 Self: Clone,
842 U: ArraySize,
843{
844 type Error = TryFromSliceError;
845
846 #[inline]
847 fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
848 Self::try_from(&*b)
849 }
850}
851
852#[cfg(feature = "alloc")]
853impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
854where
855 Self: Clone,
856 U: ArraySize,
857{
858 type Error = TryFromSliceError;
859
860 #[inline]
861 fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
862 Self::try_from(&**b)
863 }
864}
865
866#[cfg(feature = "alloc")]
867impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
868where
869 Self: Clone,
870 U: ArraySize,
871{
872 type Error = TryFromSliceError;
873
874 #[inline]
875 fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
876 Self::try_from(v.as_slice())
877 }
878}
879
880#[cfg(feature = "alloc")]
881impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
882where
883 Self: Clone,
884 U: ArraySize,
885{
886 type Error = TryFromSliceError;
887
888 #[inline]
889 fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
890 Self::try_from(v.as_slice())
891 }
892}
893
894impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
895where
896 U: ArraySize,
897{
898 type Error = TryFromSliceError;
899
900 #[inline]
901 fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
902 check_slice_length::<T, U>(slice)?;
903
904 Ok(unsafe { &*slice.as_ptr().cast() })
907 }
908}
909
910impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
911where
912 U: ArraySize,
913{
914 type Error = TryFromSliceError;
915
916 #[inline]
917 fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
918 check_slice_length::<T, U>(slice)?;
919
920 Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
923 }
924}
925
926#[cfg(feature = "bytemuck")]
927unsafe impl<T, U> Pod for Array<T, U>
928where
929 T: Pod,
930 U: ArraySize,
931 U::ArrayType<T>: Copy,
932{
933}
934
935#[cfg(feature = "bytemuck")]
936unsafe impl<T, U> Zeroable for Array<T, U>
937where
938 T: Zeroable,
939 U: ArraySize,
940{
941}
942
943#[cfg(feature = "subtle")]
944impl<T, U> ConditionallySelectable for Array<T, U>
945where
946 Self: Copy,
947 T: ConditionallySelectable,
948 U: ArraySize,
949{
950 #[inline]
951 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
952 let mut output = *a;
953 output.conditional_assign(b, choice);
954 output
955 }
956
957 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
958 for (a_i, b_i) in self.iter_mut().zip(other) {
959 a_i.conditional_assign(b_i, choice)
960 }
961 }
962}
963
964#[cfg(feature = "subtle")]
965impl<T, U> ConstantTimeEq for Array<T, U>
966where
967 T: ConstantTimeEq,
968 U: ArraySize,
969{
970 #[inline]
971 fn ct_eq(&self, other: &Self) -> Choice {
972 self.iter()
973 .zip(other.iter())
974 .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
975 }
976}
977
978#[cfg(feature = "zeroize")]
979impl<T, U> Zeroize for Array<T, U>
980where
981 T: Zeroize,
982 U: ArraySize,
983{
984 #[inline]
985 fn zeroize(&mut self) {
986 self.0.as_mut().iter_mut().zeroize()
987 }
988}
989
990#[cfg(feature = "zeroize")]
991impl<T, U> ZeroizeOnDrop for Array<T, U>
992where
993 T: ZeroizeOnDrop,
994 U: ArraySize,
995{
996}
997
998#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
1000fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
1001 debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
1002
1003 if slice.len() != U::USIZE {
1004 <&[T; 1]>::try_from([].as_slice())?;
1006
1007 #[cfg(debug_assertions)]
1008 unreachable!();
1009 }
1010
1011 Ok(())
1012}