From 230b55dcf821a25d945e8d0ddec2cea460a46935 Mon Sep 17 00:00:00 2001 From: Amogh Shivaram Date: Fri, 6 Jun 2025 22:14:30 -0500 Subject: [PATCH 1/4] Add `into_chunks` --- library/alloc/src/vec/mod.rs | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ce7321544b6b9..71fd5b409ac80 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2999,6 +2999,58 @@ impl Vec { (initialized, spare, &mut self.len) } } + + /// Groups every `N` elements in the `Vec` into chunks to produce a `Vec<[T; N]>`, dropping + /// elements in the remainder. `N` must be greater than zero. + /// + /// If the capacity is not a multiple of the chunk size, the buffer will shrink down to the + /// nearest multiple with a reallocation or deallocation. + /// + /// This function can be used to reverse [`Vec::into_flattened`]. + /// + /// # Examples + /// + /// ``` + /// let vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; + /// assert_eq!(vec.into_chunks::<3>(), [[0, 1, 2], [3, 4, 5]]); + /// + /// let vec = vec![0, 1, 2, 3]; + /// let chunks: Vec<[u8; 10]> = vec.into_chunks(); + /// assert!(chunks.is_empty()); + /// + /// let flat = vec![0; 8 * 8 * 8]; + /// let reshaped: Vec<[[[u8; 8]; 8]; 8]> = flat.into_chunks().into_chunks().into_chunks(); + /// assert_eq!(reshaped.len(), 1); + /// ``` + #[unstable(feature = "vec_into_chunks", issue = "142137")] + pub fn into_chunks(mut self) -> Vec<[T; N], A> { + const { + assert!(N != 0, "chunk size should be greater than zero"); + } + + let (len, cap) = (self.len(), self.capacity()); + + let len_remainder = len % N; + if len_remainder != 0 { + self.truncate(len - len_remainder); + } + + let cap_remainder = cap % N; + if !T::IS_ZST && cap_remainder != 0 { + self.buf.shrink_to_fit(cap - cap_remainder); + } + + let (ptr, _, _, alloc) = self.into_raw_parts_with_alloc(); + + // SAFETY: + // - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_alloc()` + // - `[T; N]` has the same alignment as `T` + // - `size_of::<[T; N]>() * cap / N == size_of::() * cap` + // - `len / N <= cap / N` because `len <= cap` + // - the allocated memory consists of `len / N` valid values of type `[T; N]` + // - `cap / N` fits the size of the allocated memory after shrinking + unsafe { Vec::from_raw_parts_in(ptr.cast(), len / N, cap / N, alloc) } + } } impl Vec { From e4e77737f9eebf1ed6a382fa4f4b8403554dad7c Mon Sep 17 00:00:00 2001 From: Amogh Shivaram Date: Fri, 6 Jun 2025 23:06:23 -0500 Subject: [PATCH 2/4] put feature attribute in example --- library/alloc/src/vec/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 71fd5b409ac80..8bd8db3b7e299 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3011,6 +3011,8 @@ impl Vec { /// # Examples /// /// ``` + /// #![feature(vec_into_chunks)] + /// /// let vec = vec![0, 1, 2, 3, 4, 5, 6, 7]; /// assert_eq!(vec.into_chunks::<3>(), [[0, 1, 2], [3, 4, 5]]); /// From 343db27aa6256ebbde88b1147eb42d41d4e77e64 Mon Sep 17 00:00:00 2001 From: Amogh Shivaram Date: Sat, 7 Jun 2025 01:14:24 -0500 Subject: [PATCH 3/4] cfg for no no_global_oom_handling --- library/alloc/src/vec/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8bd8db3b7e299..bdac38e912021 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3024,6 +3024,7 @@ impl Vec { /// let reshaped: Vec<[[[u8; 8]; 8]; 8]> = flat.into_chunks().into_chunks().into_chunks(); /// assert_eq!(reshaped.len(), 1); /// ``` + #[cfg(not(no_global_oom_handling))] #[unstable(feature = "vec_into_chunks", issue = "142137")] pub fn into_chunks(mut self) -> Vec<[T; N], A> { const { From c1d32d85339a5c06f95da49c1731ac9a3d9c2ea3 Mon Sep 17 00:00:00 2001 From: Amogh Shivaram Date: Sat, 7 Jun 2025 08:18:44 -0500 Subject: [PATCH 4/4] fix wording in assert --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index bdac38e912021..bd4273d23aa2b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3028,7 +3028,7 @@ impl Vec { #[unstable(feature = "vec_into_chunks", issue = "142137")] pub fn into_chunks(mut self) -> Vec<[T; N], A> { const { - assert!(N != 0, "chunk size should be greater than zero"); + assert!(N != 0, "chunk size must be greater than zero"); } let (len, cap) = (self.len(), self.capacity());