@@ -153,14 +153,19 @@ impl<T> TypedArena<T> {
153
153
}
154
154
}
155
155
156
+ #[ inline]
157
+ fn can_allocate ( & self , len : usize ) -> bool {
158
+ let available_capacity_bytes = self . end . get ( ) as usize - self . ptr . get ( ) as usize ;
159
+ let at_least_bytes = len * mem:: size_of :: < T > ( ) ;
160
+ available_capacity_bytes >= at_least_bytes
161
+ }
162
+
156
163
#[ inline]
157
164
fn alloc_raw_slice ( & self , len : usize ) -> * mut T {
158
165
assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
159
166
assert ! ( len != 0 ) ;
160
167
161
- let available_capacity_bytes = self . end . get ( ) as usize - self . ptr . get ( ) as usize ;
162
- let at_least_bytes = len * mem:: size_of :: < T > ( ) ;
163
- if available_capacity_bytes < at_least_bytes {
168
+ if !self . can_allocate ( len) {
164
169
self . grow ( len) ;
165
170
}
166
171
@@ -191,7 +196,39 @@ impl<T> TypedArena<T> {
191
196
192
197
pub fn alloc_from_iter < I : IntoIterator < Item =T > > ( & self , iter : I ) -> & [ T ] where T : Clone {
193
198
assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
194
- let vec: Vec < _ > = iter. into_iter ( ) . collect ( ) ;
199
+ let mut iter = iter. into_iter ( ) ;
200
+ let size_hint = iter. size_hint ( ) ;
201
+
202
+ match size_hint {
203
+ ( min, Some ( max) ) if min == max => {
204
+ if min == 0 {
205
+ return & [ ] ;
206
+ }
207
+
208
+ if !self . can_allocate ( min) {
209
+ self . grow ( min) ;
210
+ }
211
+
212
+ let slice = self . ptr . get ( ) ;
213
+
214
+ unsafe {
215
+ let mut ptr = self . ptr . get ( ) ;
216
+ for _ in 0 ..min {
217
+ // Write into uninitialized memory.
218
+ ptr:: write ( ptr, iter. next ( ) . unwrap ( ) ) ;
219
+ // Advance the pointer.
220
+ ptr = ptr. offset ( 1 ) ;
221
+ // Update the pointer per iteration so if `iter.next()` panics
222
+ // we destroy the correct amount
223
+ self . ptr . set ( ptr) ;
224
+ }
225
+ return slice:: from_raw_parts_mut ( slice, min) ;
226
+ }
227
+ }
228
+ _ => ( ) ,
229
+ }
230
+
231
+ let vec: Vec < _ > = iter. collect ( ) ;
195
232
if vec. is_empty ( ) {
196
233
return & [ ]
197
234
}
0 commit comments