@@ -153,14 +153,19 @@ impl<T> TypedArena<T> {
153153 }
154154 }
155155
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+
156163 #[ inline]
157164 fn alloc_raw_slice ( & self , len : usize ) -> * mut T {
158165 assert ! ( mem:: size_of:: <T >( ) != 0 ) ;
159166 assert ! ( len != 0 ) ;
160167
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) {
164169 self . grow ( len) ;
165170 }
166171
@@ -191,7 +196,39 @@ impl<T> TypedArena<T> {
191196
192197 pub fn alloc_from_iter < I : IntoIterator < Item =T > > ( & self , iter : I ) -> & [ T ] where T : Clone {
193198 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 ( ) ;
195232 if vec. is_empty ( ) {
196233 return & [ ]
197234 }
0 commit comments