@@ -5,6 +5,7 @@ use std::convert::TryInto;
5
5
use std:: fmt:: Debug ;
6
6
use std:: hash:: { Hash , Hasher } ;
7
7
use std:: io:: { Read , Seek , SeekFrom , Write } ;
8
+ use std:: mem:: ManuallyDrop ;
8
9
9
10
use crate :: frames:: UnresolvedFrames ;
10
11
@@ -148,6 +149,7 @@ pub struct TempFdArray<T: 'static> {
148
149
file : NamedTempFile ,
149
150
buffer : Box < [ T ; BUFFER_LENGTH ] > ,
150
151
buffer_index : usize ,
152
+ flush_n : usize ,
151
153
}
152
154
153
155
impl < T : Default + Debug > TempFdArray < T > {
@@ -162,6 +164,7 @@ impl<T: Default + Debug> TempFdArray<T> {
162
164
file,
163
165
buffer,
164
166
buffer_index : 0 ,
167
+ flush_n : 0 ,
165
168
} )
166
169
}
167
170
}
@@ -175,6 +178,7 @@ impl<T> TempFdArray<T> {
175
178
BUFFER_LENGTH * std:: mem:: size_of :: < T > ( ) ,
176
179
)
177
180
} ;
181
+ self . flush_n += 1 ;
178
182
self . file . write_all ( buf) ?;
179
183
180
184
Ok ( ( ) )
@@ -191,24 +195,50 @@ impl<T> TempFdArray<T> {
191
195
Ok ( ( ) )
192
196
}
193
197
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) ;
200
201
201
202
Ok ( TempFdArrayIterator {
202
203
buffer : & self . buffer [ 0 ..self . buffer_index ] ,
203
- file_vec ,
204
+ file_buffer ,
204
205
index : 0 ,
205
206
} )
206
207
}
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
+ }
207
237
}
208
238
209
239
pub struct TempFdArrayIterator < ' a , T > {
210
240
pub buffer : & ' a [ T ] ,
211
- pub file_vec : Vec < u8 > ,
241
+ pub file_buffer : & ' a [ ManuallyDrop < T > ] ,
212
242
pub index : usize ,
213
243
}
214
244
@@ -220,12 +250,9 @@ impl<'a, T> Iterator for TempFdArrayIterator<'a, T> {
220
250
self . index += 1 ;
221
251
Some ( & self . buffer [ self . index - 1 ] )
222
252
} 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 ( ) {
227
254
self . index += 1 ;
228
- Some ( & ts [ self . index - self . buffer . len ( ) - 1 ] )
255
+ Some ( & self . file_buffer [ self . index - self . buffer . len ( ) - 1 ] )
229
256
} else {
230
257
None
231
258
}
@@ -256,8 +283,8 @@ impl<T: Hash + Eq + 'static> Collector<T> {
256
283
Ok ( ( ) )
257
284
}
258
285
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 ) ?) )
261
288
}
262
289
}
263
290
@@ -343,7 +370,8 @@ mod tests {
343
370
}
344
371
}
345
372
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| {
347
375
test_utils:: add_map ( & mut real_map, entry) ;
348
376
} ) ;
349
377
0 commit comments