|
11 | 11 | html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
12 | 12 | test(no_crate_inject, attr(deny(warnings)))
|
13 | 13 | )]
|
| 14 | +#![feature(array_value_iter_slice)] |
14 | 15 | #![feature(dropck_eyepatch)]
|
15 | 16 | #![feature(new_uninit)]
|
16 | 17 | #![feature(maybe_uninit_slice)]
|
| 18 | +#![feature(array_value_iter)] |
| 19 | +#![feature(min_const_generics)] |
| 20 | +#![feature(min_specialization)] |
17 | 21 | #![cfg_attr(test, feature(test))]
|
18 | 22 |
|
19 | 23 | use smallvec::SmallVec;
|
@@ -114,6 +118,72 @@ impl<T> Default for TypedArena<T> {
|
114 | 118 | }
|
115 | 119 | }
|
116 | 120 |
|
| 121 | +trait IterExt<T> { |
| 122 | + fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T]; |
| 123 | +} |
| 124 | + |
| 125 | +impl<I, T> IterExt<T> for I |
| 126 | +where |
| 127 | + I: IntoIterator<Item = T>, |
| 128 | +{ |
| 129 | + #[inline] |
| 130 | + default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] { |
| 131 | + let vec: SmallVec<[_; 8]> = self.into_iter().collect(); |
| 132 | + vec.alloc_from_iter(arena) |
| 133 | + } |
| 134 | +} |
| 135 | + |
| 136 | +impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> { |
| 137 | + #[inline] |
| 138 | + fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] { |
| 139 | + let len = self.len(); |
| 140 | + if len == 0 { |
| 141 | + return &mut []; |
| 142 | + } |
| 143 | + // Move the content to the arena by copying and then forgetting it |
| 144 | + unsafe { |
| 145 | + let start_ptr = arena.alloc_raw_slice(len); |
| 146 | + self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len); |
| 147 | + mem::forget(self); |
| 148 | + slice::from_raw_parts_mut(start_ptr, len) |
| 149 | + } |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +impl<T> IterExt<T> for Vec<T> { |
| 154 | + #[inline] |
| 155 | + fn alloc_from_iter(mut self, arena: &TypedArena<T>) -> &mut [T] { |
| 156 | + let len = self.len(); |
| 157 | + if len == 0 { |
| 158 | + return &mut []; |
| 159 | + } |
| 160 | + // Move the content to the arena by copying and then forgetting it |
| 161 | + unsafe { |
| 162 | + let start_ptr = arena.alloc_raw_slice(len); |
| 163 | + self.as_ptr().copy_to_nonoverlapping(start_ptr, len); |
| 164 | + self.set_len(0); |
| 165 | + slice::from_raw_parts_mut(start_ptr, len) |
| 166 | + } |
| 167 | + } |
| 168 | +} |
| 169 | + |
| 170 | +impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> { |
| 171 | + #[inline] |
| 172 | + fn alloc_from_iter(mut self, arena: &TypedArena<A::Item>) -> &mut [A::Item] { |
| 173 | + let len = self.len(); |
| 174 | + if len == 0 { |
| 175 | + return &mut []; |
| 176 | + } |
| 177 | + // Move the content to the arena by copying and then forgetting it |
| 178 | + unsafe { |
| 179 | + let start_ptr = arena.alloc_raw_slice(len); |
| 180 | + self.as_ptr().copy_to_nonoverlapping(start_ptr, len); |
| 181 | + self.set_len(0); |
| 182 | + slice::from_raw_parts_mut(start_ptr, len) |
| 183 | + } |
| 184 | + } |
| 185 | +} |
| 186 | + |
117 | 187 | impl<T> TypedArena<T> {
|
118 | 188 | /// Allocates an object in the `TypedArena`, returning a reference to it.
|
119 | 189 | #[inline]
|
@@ -191,19 +261,7 @@ impl<T> TypedArena<T> {
|
191 | 261 | #[inline]
|
192 | 262 | pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
|
193 | 263 | assert!(mem::size_of::<T>() != 0);
|
194 |
| - let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); |
195 |
| - if vec.is_empty() { |
196 |
| - return &mut []; |
197 |
| - } |
198 |
| - // Move the content to the arena by copying it and then forgetting |
199 |
| - // the content of the SmallVec |
200 |
| - unsafe { |
201 |
| - let len = vec.len(); |
202 |
| - let start_ptr = self.alloc_raw_slice(len); |
203 |
| - vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); |
204 |
| - vec.set_len(0); |
205 |
| - slice::from_raw_parts_mut(start_ptr, len) |
206 |
| - } |
| 264 | + iter.alloc_from_iter(self) |
207 | 265 | }
|
208 | 266 |
|
209 | 267 | /// Grows the arena.
|
|
0 commit comments