88
88
89
89
extern crate alloc;
90
90
91
- use core:: ptr:: NonNull ;
91
+ #[ cfg( has_ptr_slice_from_raw_parts) ]
92
+ use core:: ptr:: slice_from_raw_parts_mut as slice_from_raw_parts;
93
+ #[ cfg( not( has_ptr_slice_from_raw_parts) ) ]
94
+ use core:: slice:: from_raw_parts_mut as slice_from_raw_parts;
92
95
#[ cfg( feature = "erasable" ) ]
93
96
use erasable:: { Erasable , ErasedPtr } ;
94
97
use {
95
98
alloc:: {
96
99
alloc:: { alloc, handle_alloc_error} ,
97
100
boxed:: Box ,
98
101
} ,
99
- core:: { alloc:: Layout , ptr, slice} ,
102
+ core:: { alloc:: Layout , mem :: ManuallyDrop , ptr, slice} ,
100
103
} ;
101
104
102
105
/// A custom slice-based dynamically sized type.
@@ -195,9 +198,18 @@ unsafe impl<S: ?Sized + SliceDst> AllocSliceDst<S> for Box<S> {
195
198
where
196
199
I : FnOnce ( ptr:: NonNull < S > ) ,
197
200
{
198
- let ptr = alloc_slice_dst ( len) ;
199
- init ( ptr) ;
200
- Box :: from_raw ( ptr. as_ptr ( ) )
201
+ struct RawBox < S : ?Sized > ( ptr:: NonNull < S > ) ;
202
+
203
+ impl < S : ?Sized > RawBox < S > {
204
+ unsafe fn finalize ( self ) -> Box < S > {
205
+ let this = ManuallyDrop :: new ( self ) ;
206
+ Box :: from_raw ( this. 0 . as_ptr ( ) )
207
+ }
208
+ }
209
+
210
+ let ptr = RawBox ( alloc_slice_dst ( len) ) ;
211
+ init ( ptr. 0 ) ;
212
+ ptr. finalize ( )
201
213
}
202
214
}
203
215
@@ -221,7 +233,7 @@ unsafe impl<Header, Item> SliceDst for SliceWithHeader<Header, Item> {
221
233
Self :: layout ( len) . 0
222
234
}
223
235
224
- fn retype ( ptr : NonNull < [ ( ) ] > ) -> NonNull < Self > {
236
+ fn retype ( ptr : ptr :: NonNull < [ ( ) ] > ) -> ptr :: NonNull < Self > {
225
237
unsafe { ptr:: NonNull :: new_unchecked ( ptr. as_ptr ( ) as * mut _ ) }
226
238
}
227
239
}
@@ -246,30 +258,91 @@ impl<Header, Item> SliceWithHeader<Header, Item> {
246
258
I : IntoIterator < Item = Item > ,
247
259
I :: IntoIter : ExactSizeIterator ,
248
260
{
249
- let mut items = items. into_iter ( ) ;
261
+ let items = items. into_iter ( ) ;
250
262
let len = items. len ( ) ;
251
- let ( layout, [ length_offset, header_offset, slice_offset] ) = Self :: layout ( len) ;
252
-
253
- unsafe {
254
- A :: new_slice_dst ( len, |ptr| {
255
- let raw = ptr. as_ptr ( ) . cast :: < u8 > ( ) ;
256
- ptr:: write ( raw. add ( length_offset) . cast ( ) , len) ;
257
- ptr:: write ( raw. add ( header_offset) . cast ( ) , header) ;
258
- let mut slice_ptr = raw. add ( slice_offset) . cast :: < Item > ( ) ;
259
- for _ in 0 ..len {
260
- let item = items
261
- . next ( )
262
- . expect ( "ExactSizeIterator over-reported length" ) ;
263
- ptr:: write ( slice_ptr, item) ;
264
- slice_ptr = slice_ptr. offset ( 1 ) ;
263
+
264
+ struct InProgress < Header , Item > {
265
+ raw : ptr:: NonNull < SliceWithHeader < Header , Item > > ,
266
+ written : usize ,
267
+ layout : Layout ,
268
+ length_offset : usize ,
269
+ header_offset : usize ,
270
+ slice_offset : usize ,
271
+ }
272
+
273
+ impl < Header , Item > Drop for InProgress < Header , Item > {
274
+ fn drop ( & mut self ) {
275
+ unsafe {
276
+ ptr:: drop_in_place ( slice_from_raw_parts (
277
+ self . raw ( ) . add ( self . slice_offset ) . cast :: < Item > ( ) ,
278
+ self . written ,
279
+ ) ) ;
280
+ }
281
+ }
282
+ }
283
+
284
+ impl < Header , Item > InProgress < Header , Item > {
285
+ fn init (
286
+ len : usize ,
287
+ header : Header ,
288
+ mut items : impl Iterator < Item = Item > + ExactSizeIterator ,
289
+ ) -> impl FnOnce ( ptr:: NonNull < SliceWithHeader < Header , Item > > ) {
290
+ move |ptr| {
291
+ let mut this = Self :: new ( len, ptr) ;
292
+
293
+ unsafe {
294
+ for _ in 0 ..len {
295
+ let item = items
296
+ . next ( )
297
+ . expect ( "ExactSizeIterator over-reported length" ) ;
298
+ this. push ( item) ;
299
+ }
300
+
301
+ assert ! (
302
+ items. next( ) . is_none( ) ,
303
+ "ExactSizeIterator under-reported length"
304
+ ) ;
305
+
306
+ this. finish ( len, header)
307
+ }
308
+ }
309
+ }
310
+
311
+ fn raw ( & self ) -> * mut u8 {
312
+ self . raw . as_ptr ( ) . cast ( )
313
+ }
314
+
315
+ fn new ( len : usize , raw : ptr:: NonNull < SliceWithHeader < Header , Item > > ) -> Self {
316
+ let ( layout, [ length_offset, header_offset, slice_offset] ) =
317
+ SliceWithHeader :: < Header , Item > :: layout ( len) ;
318
+ InProgress {
319
+ raw,
320
+ written : 0 ,
321
+ layout,
322
+ length_offset,
323
+ header_offset,
324
+ slice_offset,
265
325
}
266
- assert ! (
267
- items. next( ) . is_none( ) ,
268
- "ExactSizeIterator under-reported length"
269
- ) ;
270
- assert_eq ! ( layout, Layout :: for_value( ptr. as_ref( ) ) ) ;
271
- } )
326
+ }
327
+
328
+ unsafe fn push ( & mut self , item : Item ) {
329
+ self . raw ( )
330
+ . add ( self . slice_offset )
331
+ . cast :: < Item > ( )
332
+ . add ( self . written )
333
+ . write ( item) ;
334
+ self . written += 1 ;
335
+ }
336
+
337
+ unsafe fn finish ( self , len : usize , header : Header ) {
338
+ let this = ManuallyDrop :: new ( self ) ;
339
+ ptr:: write ( this. raw ( ) . add ( this. length_offset ) . cast ( ) , len) ;
340
+ ptr:: write ( this. raw ( ) . add ( this. header_offset ) . cast ( ) , header) ;
341
+ debug_assert_eq ! ( this. layout, Layout :: for_value( this. raw. as_ref( ) ) )
342
+ }
272
343
}
344
+
345
+ unsafe { A :: new_slice_dst ( len, InProgress :: init ( len, header, items) ) }
273
346
}
274
347
}
275
348
@@ -286,11 +359,6 @@ where
286
359
#[ cfg( feature = "erasable" ) ]
287
360
unsafe impl < Header , Item > Erasable for SliceWithHeader < Header , Item > {
288
361
unsafe fn unerase ( this : ErasedPtr ) -> ptr:: NonNull < Self > {
289
- #[ cfg( not( has_ptr_slice_from_raw_parts) ) ]
290
- let slice_from_raw_parts = slice:: from_raw_parts_mut :: < ( ) > ;
291
- #[ cfg( has_ptr_slice_from_raw_parts) ]
292
- let slice_from_raw_parts = ptr:: slice_from_raw_parts_mut :: < ( ) > ;
293
-
294
362
let len: usize = ptr:: read ( this. as_ptr ( ) . cast ( ) ) ;
295
363
let raw = ptr:: NonNull :: new_unchecked ( slice_from_raw_parts ( this. as_ptr ( ) . cast ( ) , len) ) ;
296
364
Self :: retype ( raw)
0 commit comments