diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-04-08 11:48:21 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-08 11:48:21 +0200 |
| commit | d5232c6b93db1d5a95b14838cc2094a000e67b3e (patch) | |
| tree | 72278b92f1eb9f43505c5dccebc9d4f236f78a49 /library/alloc/src | |
| parent | 94ffb29ee4441246ec3da1f207891549409ce7b1 (diff) | |
| parent | 06788fd7a4c89479dfe28c1e42410778adf41eab (diff) | |
| download | rust-d5232c6b93db1d5a95b14838cc2094a000e67b3e.tar.gz rust-d5232c6b93db1d5a95b14838cc2094a000e67b3e.zip | |
Rollup merge of #95579 - Cyborus04:slice_flatten, r=scottmcm
Add `<[[T; N]]>::flatten{_mut}`
Adds `flatten` to convert `&[[T; N]]` to `&[T]` (and `flatten_mut` for `&mut [[T; N]]` to `&mut [T]`)
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 45 |
2 files changed, 46 insertions, 0 deletions
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 72d6c267290..2ddb5f231b1 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -131,6 +131,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] // diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 0b62622de81..74bcac2b541 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2274,6 +2274,51 @@ impl<T: Clone, A: Allocator> Vec<T, A> { } } +impl<T, A: Allocator, const N: usize> Vec<[T; N], A> { + /// Takes a `Vec<[T; N]>` and flattens it into a `Vec<T>`. + /// + /// # Panics + /// + /// Panics if the length of the resulting vector would overflow a `usize`. + /// + /// This is only possible when flattening a vector of arrays of zero-sized + /// types, and thus tends to be irrelevant in practice. If + /// `size_of::<T>() > 0`, this will never panic. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_flatten)] + /// + /// let mut vec = vec![[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + /// assert_eq!(vec.pop(), Some([7, 8, 9])); + /// + /// let mut flattened = vec.into_flattened(); + /// assert_eq!(flattened.pop(), Some(6)); + /// ``` + #[unstable(feature = "slice_flatten", issue = "95629")] + pub fn into_flattened(self) -> Vec<T, A> { + let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); + let (new_len, new_cap) = if mem::size_of::<T>() == 0 { + (len.checked_mul(N).expect("vec len overflow"), usize::MAX) + } else { + // SAFETY: + // - `cap * N` cannot overflow because the allocation is already in + // the address space. + // - Each `[T; N]` has `N` valid elements, so there are `len * N` + // valid elements in the allocation. + unsafe { (len.unchecked_mul(N), cap.unchecked_mul(N)) } + }; + // SAFETY: + // - `ptr` was allocated by `self` + // - `ptr` is well-aligned because `[T; N]` has the same alignment as `T`. + // - `new_cap` refers to the same sized allocation as `cap` because + // `new_cap * size_of::<T>()` == `cap * size_of::<[T; N]>()` + // - `len` <= `cap`, so `len * N` <= `cap * N`. + unsafe { Vec::<T, A>::from_raw_parts_in(ptr.cast(), new_len, new_cap, alloc) } + } +} + // This code generalizes `extend_with_{element,default}`. trait ExtendWith<T> { fn next(&mut self) -> T; |
