Skip to content

Commit 230b55d

Browse files
committed
Add into_chunks
1 parent 868bf2d commit 230b55d

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

library/alloc/src/vec/mod.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,6 +2999,58 @@ impl<T, A: Allocator> Vec<T, A> {
29992999
(initialized, spare, &mut self.len)
30003000
}
30013001
}
3002+
3003+
/// Groups every `N` elements in the `Vec<T>` into chunks to produce a `Vec<[T; N]>`, dropping
3004+
/// elements in the remainder. `N` must be greater than zero.
3005+
///
3006+
/// If the capacity is not a multiple of the chunk size, the buffer will shrink down to the
3007+
/// nearest multiple with a reallocation or deallocation.
3008+
///
3009+
/// This function can be used to reverse [`Vec::into_flattened`].
3010+
///
3011+
/// # Examples
3012+
///
3013+
/// ```
3014+
/// let vec = vec![0, 1, 2, 3, 4, 5, 6, 7];
3015+
/// assert_eq!(vec.into_chunks::<3>(), [[0, 1, 2], [3, 4, 5]]);
3016+
///
3017+
/// let vec = vec![0, 1, 2, 3];
3018+
/// let chunks: Vec<[u8; 10]> = vec.into_chunks();
3019+
/// assert!(chunks.is_empty());
3020+
///
3021+
/// let flat = vec![0; 8 * 8 * 8];
3022+
/// let reshaped: Vec<[[[u8; 8]; 8]; 8]> = flat.into_chunks().into_chunks().into_chunks();
3023+
/// assert_eq!(reshaped.len(), 1);
3024+
/// ```
3025+
#[unstable(feature = "vec_into_chunks", issue = "142137")]
3026+
pub fn into_chunks<const N: usize>(mut self) -> Vec<[T; N], A> {
3027+
const {
3028+
assert!(N != 0, "chunk size should be greater than zero");
3029+
}
3030+
3031+
let (len, cap) = (self.len(), self.capacity());
3032+
3033+
let len_remainder = len % N;
3034+
if len_remainder != 0 {
3035+
self.truncate(len - len_remainder);
3036+
}
3037+
3038+
let cap_remainder = cap % N;
3039+
if !T::IS_ZST && cap_remainder != 0 {
3040+
self.buf.shrink_to_fit(cap - cap_remainder);
3041+
}
3042+
3043+
let (ptr, _, _, alloc) = self.into_raw_parts_with_alloc();
3044+
3045+
// SAFETY:
3046+
// - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_alloc()`
3047+
// - `[T; N]` has the same alignment as `T`
3048+
// - `size_of::<[T; N]>() * cap / N == size_of::<T>() * cap`
3049+
// - `len / N <= cap / N` because `len <= cap`
3050+
// - the allocated memory consists of `len / N` valid values of type `[T; N]`
3051+
// - `cap / N` fits the size of the allocated memory after shrinking
3052+
unsafe { Vec::from_raw_parts_in(ptr.cast(), len / N, cap / N, alloc) }
3053+
}
30023054
}
30033055

30043056
impl<T: Clone, A: Allocator> Vec<T, A> {

0 commit comments

Comments
 (0)