@@ -888,6 +888,46 @@ impl<T> [T] {
888
888
ChunksExactMut :: new ( self , chunk_size)
889
889
}
890
890
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
+
891
931
/// Splits the slice into a slice of `N`-element arrays,
892
932
/// starting at the beginning of the slice,
893
933
/// and a remainder slice with length strictly less than `N`.
@@ -912,12 +952,42 @@ impl<T> [T] {
912
952
assert_ne ! ( N , 0 ) ;
913
953
let len = self . len ( ) / N ;
914
954
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 ( ) } ;
918
958
( array_slice, remainder)
919
959
}
920
960
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
+
921
991
/// Returns an iterator over `N` elements of the slice at a time, starting at the
922
992
/// beginning of the slice.
923
993
///
@@ -952,6 +1022,48 @@ impl<T> [T] {
952
1022
ArrayChunks :: new ( self )
953
1023
}
954
1024
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
+
955
1067
/// Splits the slice into a slice of `N`-element arrays,
956
1068
/// starting at the beginning of the slice,
957
1069
/// and a remainder slice with length strictly less than `N`.
@@ -982,13 +1094,48 @@ impl<T> [T] {
982
1094
assert_ne ! ( N , 0 ) ;
983
1095
let len = self . len ( ) / N ;
984
1096
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 ( ) } ;
989
1100
( array_slice, remainder)
990
1101
}
991
1102
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
+
992
1139
/// Returns an iterator over `N` elements of the slice at a time, starting at the
993
1140
/// beginning of the slice.
994
1141
///
0 commit comments