@@ -888,6 +888,46 @@ impl<T> [T] {
888888 ChunksExactMut :: new ( self , chunk_size)
889889 }
890890
891+ /// Splits the slice into a slice of `N`-element arrays,
892+ /// assuming that there's no remainder.
893+ ///
894+ /// # Safety
895+ ///
896+ /// This may only be called when
897+ /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
898+ /// - `N != 0`.
899+ ///
900+ /// # Examples
901+ ///
902+ /// ```
903+ /// #![feature(slice_as_chunks)]
904+ /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
905+ /// let chunks: &[[char; 1]] =
906+ /// // SAFETY: 1-element chunks never have remainder
907+ /// unsafe { slice.as_chunks_unchecked() };
908+ /// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
909+ /// let chunks: &[[char; 3]] =
910+ /// // SAFETY: The slice length (6) is a multiple of 3
911+ /// unsafe { slice.as_chunks_unchecked() };
912+ /// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
913+ ///
914+ /// // These would be unsound:
915+ /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
916+ /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
917+ /// ```
918+ #[ unstable( feature = "slice_as_chunks" , issue = "74985" ) ]
919+ #[ inline]
920+ pub unsafe fn as_chunks_unchecked < const N : usize > ( & self ) -> & [ [ T ; N ] ] {
921+ debug_assert_ne ! ( N , 0 ) ;
922+ debug_assert_eq ! ( self . len( ) % N , 0 ) ;
923+ let new_len =
924+ // SAFETY: Our precondition is exactly what's needed to call this
925+ unsafe { crate :: intrinsics:: exact_div ( self . len ( ) , N ) } ;
926+ // SAFETY: We cast a slice of `new_len * N` elements into
927+ // a slice of `new_len` many `N` elements chunks.
928+ unsafe { from_raw_parts ( self . as_ptr ( ) . cast ( ) , new_len) }
929+ }
930+
891931 /// Splits the slice into a slice of `N`-element arrays,
892932 /// starting at the beginning of the slice,
893933 /// and a remainder slice with length strictly less than `N`.
@@ -912,12 +952,42 @@ impl<T> [T] {
912952 assert_ne ! ( N , 0 ) ;
913953 let len = self . len ( ) / N ;
914954 let ( multiple_of_n, remainder) = self . split_at ( len * N ) ;
915- // SAFETY: We cast a slice of `len * N` elements into
916- // a slice of `len` many `N` elements chunks .
917- let array_slice: & [ [ T ; N ] ] = unsafe { from_raw_parts ( multiple_of_n. as_ptr ( ) . cast ( ) , len ) } ;
955+ // SAFETY: We already panicked for zero, and ensured by construction
956+ // that the length of the subslice is a multiple of N .
957+ let array_slice = unsafe { multiple_of_n. as_chunks_unchecked ( ) } ;
918958 ( array_slice, remainder)
919959 }
920960
961+ /// Splits the slice into a slice of `N`-element arrays,
962+ /// starting at the end of the slice,
963+ /// and a remainder slice with length strictly less than `N`.
964+ ///
965+ /// # Panics
966+ ///
967+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
968+ /// error before this method gets stabilized.
969+ ///
970+ /// # Examples
971+ ///
972+ /// ```
973+ /// #![feature(slice_as_chunks)]
974+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
975+ /// let (remainder, chunks) = slice.as_rchunks();
976+ /// assert_eq!(remainder, &['l']);
977+ /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
978+ /// ```
979+ #[ unstable( feature = "slice_as_chunks" , issue = "74985" ) ]
980+ #[ inline]
981+ pub fn as_rchunks < const N : usize > ( & self ) -> ( & [ T ] , & [ [ T ; N ] ] ) {
982+ assert_ne ! ( N , 0 ) ;
983+ let len = self . len ( ) / N ;
984+ let ( remainder, multiple_of_n) = self . split_at ( self . len ( ) - len * N ) ;
985+ // SAFETY: We already panicked for zero, and ensured by construction
986+ // that the length of the subslice is a multiple of N.
987+ let array_slice = unsafe { multiple_of_n. as_chunks_unchecked ( ) } ;
988+ ( remainder, array_slice)
989+ }
990+
921991 /// Returns an iterator over `N` elements of the slice at a time, starting at the
922992 /// beginning of the slice.
923993 ///
@@ -952,6 +1022,48 @@ impl<T> [T] {
9521022 ArrayChunks :: new ( self )
9531023 }
9541024
1025+ /// Splits the slice into a slice of `N`-element arrays,
1026+ /// assuming that there's no remainder.
1027+ ///
1028+ /// # Safety
1029+ ///
1030+ /// This may only be called when
1031+ /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
1032+ /// - `N != 0`.
1033+ ///
1034+ /// # Examples
1035+ ///
1036+ /// ```
1037+ /// #![feature(slice_as_chunks)]
1038+ /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
1039+ /// let chunks: &mut [[char; 1]] =
1040+ /// // SAFETY: 1-element chunks never have remainder
1041+ /// unsafe { slice.as_chunks_unchecked_mut() };
1042+ /// chunks[0] = ['L'];
1043+ /// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
1044+ /// let chunks: &mut [[char; 3]] =
1045+ /// // SAFETY: The slice length (6) is a multiple of 3
1046+ /// unsafe { slice.as_chunks_unchecked_mut() };
1047+ /// chunks[1] = ['a', 'x', '?'];
1048+ /// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
1049+ ///
1050+ /// // These would be unsound:
1051+ /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut() // The slice length is not a multiple of 5
1052+ /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
1053+ /// ```
1054+ #[ unstable( feature = "slice_as_chunks" , issue = "74985" ) ]
1055+ #[ inline]
1056+ pub unsafe fn as_chunks_unchecked_mut < const N : usize > ( & mut self ) -> & mut [ [ T ; N ] ] {
1057+ debug_assert_ne ! ( N , 0 ) ;
1058+ debug_assert_eq ! ( self . len( ) % N , 0 ) ;
1059+ let new_len =
1060+ // SAFETY: Our precondition is exactly what's needed to call this
1061+ unsafe { crate :: intrinsics:: exact_div ( self . len ( ) , N ) } ;
1062+ // SAFETY: We cast a slice of `new_len * N` elements into
1063+ // a slice of `new_len` many `N` elements chunks.
1064+ unsafe { from_raw_parts_mut ( self . as_mut_ptr ( ) . cast ( ) , new_len) }
1065+ }
1066+
9551067 /// Splits the slice into a slice of `N`-element arrays,
9561068 /// starting at the beginning of the slice,
9571069 /// and a remainder slice with length strictly less than `N`.
@@ -982,13 +1094,48 @@ impl<T> [T] {
9821094 assert_ne ! ( N , 0 ) ;
9831095 let len = self . len ( ) / N ;
9841096 let ( multiple_of_n, remainder) = self . split_at_mut ( len * N ) ;
985- let array_slice: & mut [ [ T ; N ] ] =
986- // SAFETY: We cast a slice of `len * N` elements into
987- // a slice of `len` many `N` elements chunks.
988- unsafe { from_raw_parts_mut ( multiple_of_n. as_mut_ptr ( ) . cast ( ) , len) } ;
1097+ // SAFETY: We already panicked for zero, and ensured by construction
1098+ // that the length of the subslice is a multiple of N.
1099+ let array_slice = unsafe { multiple_of_n. as_chunks_unchecked_mut ( ) } ;
9891100 ( array_slice, remainder)
9901101 }
9911102
1103+ /// Splits the slice into a slice of `N`-element arrays,
1104+ /// starting at the end of the slice,
1105+ /// and a remainder slice with length strictly less than `N`.
1106+ ///
1107+ /// # Panics
1108+ ///
1109+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
1110+ /// error before this method gets stabilized.
1111+ ///
1112+ /// # Examples
1113+ ///
1114+ /// ```
1115+ /// #![feature(slice_as_chunks)]
1116+ /// let v = &mut [0, 0, 0, 0, 0];
1117+ /// let mut count = 1;
1118+ ///
1119+ /// let (remainder, chunks) = v.as_rchunks_mut();
1120+ /// remainder[0] = 9;
1121+ /// for chunk in chunks {
1122+ /// *chunk = [count; 2];
1123+ /// count += 1;
1124+ /// }
1125+ /// assert_eq!(v, &[9, 1, 1, 2, 2]);
1126+ /// ```
1127+ #[ unstable( feature = "slice_as_chunks" , issue = "74985" ) ]
1128+ #[ inline]
1129+ pub fn as_rchunks_mut < const N : usize > ( & mut self ) -> ( & mut [ T ] , & mut [ [ T ; N ] ] ) {
1130+ assert_ne ! ( N , 0 ) ;
1131+ let len = self . len ( ) / N ;
1132+ let ( remainder, multiple_of_n) = self . split_at_mut ( self . len ( ) - len * N ) ;
1133+ // SAFETY: We already panicked for zero, and ensured by construction
1134+ // that the length of the subslice is a multiple of N.
1135+ let array_slice = unsafe { multiple_of_n. as_chunks_unchecked_mut ( ) } ;
1136+ ( remainder, array_slice)
1137+ }
1138+
9921139 /// Returns an iterator over `N` elements of the slice at a time, starting at the
9931140 /// beginning of the slice.
9941141 ///
0 commit comments