@@ -5,6 +5,7 @@ use std::convert::TryInto;
55use std:: fmt:: Debug ;
66use std:: hash:: { Hash , Hasher } ;
77use std:: io:: { Read , Seek , SeekFrom , Write } ;
8+ use std:: mem:: ManuallyDrop ;
89
910use crate :: frames:: UnresolvedFrames ;
1011
@@ -148,6 +149,7 @@ pub struct TempFdArray<T: 'static> {
148149 file : NamedTempFile ,
149150 buffer : Box < [ T ; BUFFER_LENGTH ] > ,
150151 buffer_index : usize ,
152+ flush_n : usize ,
151153}
152154
153155impl < T : Default + Debug > TempFdArray < T > {
@@ -162,6 +164,7 @@ impl<T: Default + Debug> TempFdArray<T> {
162164 file,
163165 buffer,
164166 buffer_index : 0 ,
167+ flush_n : 0 ,
165168 } )
166169 }
167170}
@@ -175,6 +178,7 @@ impl<T> TempFdArray<T> {
175178 BUFFER_LENGTH * std:: mem:: size_of :: < T > ( ) ,
176179 )
177180 } ;
181+ self . flush_n += 1 ;
178182 self . file . write_all ( buf) ?;
179183
180184 Ok ( ( ) )
@@ -191,24 +195,50 @@ impl<T> TempFdArray<T> {
191195 Ok ( ( ) )
192196 }
193197
194- fn try_iter ( & self ) -> std:: io:: Result < impl Iterator < Item = & T > > {
195- let mut file_vec = Vec :: new ( ) ;
196- let mut file = self . file . reopen ( ) ?;
197- file. seek ( SeekFrom :: Start ( 0 ) ) ?;
198- file. read_to_end ( & mut file_vec) ?;
199- file. seek ( SeekFrom :: End ( 0 ) ) ?;
198+ fn try_iter < ' lt > ( & ' lt self , file_buffer_container : & ' lt mut Option < Box < [ ManuallyDrop < T > ] > > ) -> std:: io:: Result < impl Iterator < Item = & ' lt T > > {
199+ let file_buffer = self . file_buffer ( ) ?;
200+ let file_buffer = file_buffer_container. insert ( file_buffer) ;
200201
201202 Ok ( TempFdArrayIterator {
202203 buffer : & self . buffer [ 0 ..self . buffer_index ] ,
203- file_vec ,
204+ file_buffer ,
204205 index : 0 ,
205206 } )
206207 }
208+
209+ fn file_buffer ( & self ) -> std:: io:: Result < Box < [ ManuallyDrop < T > ] > > {
210+ if self . flush_n == 0 {
211+ return Ok ( Vec :: new ( ) . into_boxed_slice ( ) )
212+ }
213+
214+ let mut file = self . file . reopen ( ) ?;
215+ file. seek ( SeekFrom :: Start ( 0 ) ) ?;
216+ let file_buffer = unsafe {
217+ // Get properly aligned pointer
218+ let len = BUFFER_LENGTH * self . flush_n ;
219+ // Expect T to be non-ZST
220+ let layout = std:: alloc:: Layout :: array :: < ManuallyDrop < T > > ( len) . unwrap ( ) ;
221+ let ptr = std:: alloc:: alloc ( layout) ;
222+ if ptr. is_null ( ) {
223+ std:: alloc:: handle_alloc_error ( layout) ;
224+ }
225+ // Populate with bytes
226+ file. read_exact ( std:: slice:: from_raw_parts_mut (
227+ ptr,
228+ len * std:: mem:: size_of :: < T > ( ) ,
229+ ) ) ?;
230+ // Cast to proper type
231+ Box :: from_raw ( std:: ptr:: slice_from_raw_parts_mut ( ptr. cast :: < ManuallyDrop < T > > ( ) , len) )
232+ } ;
233+ file. seek ( SeekFrom :: End ( 0 ) ) ?;
234+
235+ Ok ( file_buffer)
236+ }
207237}
208238
209239pub struct TempFdArrayIterator < ' a , T > {
210240 pub buffer : & ' a [ T ] ,
211- pub file_vec : Vec < u8 > ,
241+ pub file_buffer : & ' a [ ManuallyDrop < T > ] ,
212242 pub index : usize ,
213243}
214244
@@ -220,12 +250,9 @@ impl<'a, T> Iterator for TempFdArrayIterator<'a, T> {
220250 self . index += 1 ;
221251 Some ( & self . buffer [ self . index - 1 ] )
222252 } else {
223- let length = self . file_vec . len ( ) / std:: mem:: size_of :: < T > ( ) ;
224- let ts =
225- unsafe { std:: slice:: from_raw_parts ( self . file_vec . as_ptr ( ) as * const T , length) } ;
226- if self . index - self . buffer . len ( ) < ts. len ( ) {
253+ if self . index - self . buffer . len ( ) < self . file_buffer . len ( ) {
227254 self . index += 1 ;
228- Some ( & ts [ self . index - self . buffer . len ( ) - 1 ] )
255+ Some ( & self . file_buffer [ self . index - self . buffer . len ( ) - 1 ] )
229256 } else {
230257 None
231258 }
@@ -256,8 +283,8 @@ impl<T: Hash + Eq + 'static> Collector<T> {
256283 Ok ( ( ) )
257284 }
258285
259- pub fn try_iter ( & self ) -> std:: io:: Result < impl Iterator < Item = & Entry < T > > > {
260- Ok ( self . map . iter ( ) . chain ( self . temp_array . try_iter ( ) ?) )
286+ pub fn try_iter < ' lt > ( & ' lt self , file_buffer_store : & ' lt mut Option < Box < [ ManuallyDrop < Entry < T > > ] > > ) -> std:: io:: Result < impl Iterator < Item = & ' lt Entry < T > > > {
287+ Ok ( self . map . iter ( ) . chain ( self . temp_array . try_iter ( file_buffer_store ) ?) )
261288 }
262289}
263290
@@ -343,7 +370,8 @@ mod tests {
343370 }
344371 }
345372
346- collector. try_iter ( ) . unwrap ( ) . for_each ( |entry| {
373+ let mut file_buffer_store = None ;
374+ collector. try_iter ( & mut file_buffer_store) . unwrap ( ) . for_each ( |entry| {
347375 test_utils:: add_map ( & mut real_map, entry) ;
348376 } ) ;
349377
0 commit comments