@@ -295,50 +295,170 @@ impl RingBuffer {
295
295
/// 2. More then len reserved space so we do not write out-of-bounds
296
296
#[ warn( unsafe_op_in_unsafe_fn) ]
297
297
pub unsafe fn extend_from_within_unchecked ( & mut self , start : usize , len : usize ) {
298
+ debug_assert ! ( start + len <= self . len( ) ) ;
299
+ debug_assert ! ( self . free( ) >= len) ;
300
+
298
301
if self . head < self . tail {
299
- // continous data slice |____HDDDDDDDT_____|
302
+ // Continuous source section and possibly non continuous write section:
303
+ //
304
+ // H T
305
+ // Read: ____XXXXSSSSXXXX________
306
+ // Write: ________________DDDD____
307
+ //
308
+ // H: Head position (first readable byte)
309
+ // T: Tail position (first writable byte)
310
+ // X: Uninvolved bytes in the readable section
311
+ // S: Source bytes, to be copied to D bytes
312
+ // D: Destination bytes, going to be copied from S bytes
313
+ // _: Uninvolved bytes in the writable section
300
314
let after_tail = usize:: min ( len, self . cap - self . tail ) ;
301
- unsafe {
315
+
316
+ let src = (
317
+ // SAFETY: `len <= isize::MAX` and fits the memory range of `buf`
318
+ unsafe { self . buf . as_ptr ( ) . add ( self . head + start) } . cast_const ( ) ,
319
+ // Src length (see above diagram)
320
+ self . tail - self . head - start,
321
+ ) ;
322
+
323
+ let dst = (
324
+ // SAFETY: `len <= isize::MAX` and fits the memory range of `buf`
325
+ unsafe { self . buf . as_ptr ( ) . add ( self . tail ) } ,
326
+ // Dst length (see above diagram)
327
+ self . cap - self . tail ,
328
+ ) ;
329
+
330
+ // SAFETY: `src` points at initialized data, `dst` points to writable memory
331
+ // and does not overlap `src`.
332
+ unsafe { copy_bytes_overshooting ( src, dst, after_tail) }
333
+
334
+ if after_tail < len {
335
+ // The write section was not continuous:
336
+ //
337
+ // H T
338
+ // Read: ____XXXXSSSSXXXX__
339
+ // Write: DD______________DD
340
+ //
341
+ // H: Head position (first readable byte)
342
+ // T: Tail position (first writable byte)
343
+ // X: Uninvolved bytes in the readable section
344
+ // S: Source bytes, to be copied to D bytes
345
+ // D: Destination bytes, going to be copied from S bytes
346
+ // _: Uninvolved bytes in the writable section
347
+
302
348
let src = (
303
- self . buf . as_ptr ( ) . cast_const ( ) . add ( self . head + start) ,
304
- self . tail - self . head ,
349
+ // SAFETY: we are still within the memory range of `buf`
350
+ unsafe { src. 0 . add ( after_tail) } ,
351
+ // Src length (see above diagram)
352
+ src. 1 - after_tail,
353
+ ) ;
354
+ let dst = (
355
+ self . buf . as_ptr ( ) ,
356
+ // Dst length overflowing (see above diagram)
357
+ self . head ,
305
358
) ;
306
- let dst = ( self . buf . as_ptr ( ) . add ( self . tail ) , self . cap - self . tail ) ;
307
- copy_bytes_overshooting ( src, dst, after_tail) ;
308
359
309
- if after_tail < len {
310
- let src = ( src. 0 . add ( after_tail) , src. 1 - after_tail) ;
311
- let dst = ( self . buf . as_ptr ( ) , self . head ) ;
312
- copy_bytes_overshooting ( src, dst, len - after_tail) ;
313
- }
360
+ // SAFETY: `src` points at initialized data, `dst` points to writable memory
361
+ // and does not overlap `src`.
362
+ unsafe { copy_bytes_overshooting ( src, dst, len - after_tail) }
314
363
}
315
364
} else {
316
- // continous free slice |DDDT_________HDDDD|
317
365
if self . head + start > self . cap {
366
+ // Continuous read section and destination section:
367
+ //
368
+ // T H
369
+ // Read: XXSSSSXXXX____________XX
370
+ // Write: __________DDDD__________
371
+ //
372
+ // H: Head position (first readable byte)
373
+ // T: Tail position (first writable byte)
374
+ // X: Uninvolved bytes in the readable section
375
+ // S: Source bytes, to be copied to D bytes
376
+ // D: Destination bytes, going to be copied from S bytes
377
+ // _: Uninvolved bytes in the writable section
378
+
318
379
let start = ( self . head + start) % self . cap ;
319
- unsafe {
320
- let src = (
321
- self . buf . as_ptr ( ) . add ( start) . cast_const ( ) ,
322
- self . cap - self . head ,
323
- ) ;
324
- let dst = ( self . buf . as_ptr ( ) . add ( self . tail ) , self . head - self . tail ) ;
325
- copy_bytes_overshooting ( src, dst, len) ;
326
- }
380
+
381
+ let src = (
382
+ // SAFETY: `len <= isize::MAX` and fits the memory range of `buf`
383
+ unsafe { self . buf . as_ptr ( ) . add ( start) } . cast_const ( ) ,
384
+ // Src length (see above diagram)
385
+ self . tail - start,
386
+ ) ;
387
+
388
+ let dst = (
389
+ // SAFETY: `len <= isize::MAX` and fits the memory range of `buf`
390
+ unsafe { self . buf . as_ptr ( ) . add ( self . tail ) } , // Dst length (see above diagram)
391
+ // Dst length (see above diagram)
392
+ self . head - self . tail ,
393
+ ) ;
394
+
395
+ // SAFETY: `src` points at initialized data, `dst` points to writable memory
396
+ // and does not overlap `src`.
397
+ unsafe { copy_bytes_overshooting ( src, dst, len) }
327
398
} else {
399
+ // Possibly non continuous read section and continuous destination section:
400
+ //
401
+ // T H
402
+ // Read: XXXX____________XXSSSSXX
403
+ // Write: ____DDDD________________
404
+ //
405
+ // H: Head position (first readable byte)
406
+ // T: Tail position (first writable byte)
407
+ // X: Uninvolved bytes in the readable section
408
+ // S: Source bytes, to be copied to D bytes
409
+ // D: Destination bytes, going to be copied from S bytes
410
+ // _: Uninvolved bytes in the writable section
411
+
328
412
let after_start = usize:: min ( len, self . cap - self . head - start) ;
329
- unsafe {
413
+
414
+ let src = (
415
+ // SAFETY: `len <= isize::MAX` and fits the memory range of `buf`
416
+ unsafe { self . buf . as_ptr ( ) . add ( self . head + start) } . cast_const ( ) ,
417
+ // Src length - chunk 1 (see above diagram on the right)
418
+ self . cap - self . head - start,
419
+ ) ;
420
+
421
+ let dst = (
422
+ // SAFETY: `len <= isize::MAX` and fits the memory range of `buf`
423
+ unsafe { self . buf . as_ptr ( ) . add ( self . tail ) } ,
424
+ // Dst length (see above diagram)
425
+ self . head - self . tail ,
426
+ ) ;
427
+
428
+ // SAFETY: `src` points at initialized data, `dst` points to writable memory
429
+ // and does not overlap `src`.
430
+ unsafe { copy_bytes_overshooting ( src, dst, after_start) }
431
+
432
+ if after_start < len {
433
+ // The read section was not continuous:
434
+ //
435
+ // T H
436
+ // Read: SSXXXXXX____________XXSS
437
+ // Write: ________DDDD____________
438
+ //
439
+ // H: Head position (first readable byte)
440
+ // T: Tail position (first writable byte)
441
+ // X: Uninvolved bytes in the readable section
442
+ // S: Source bytes, to be copied to D bytes
443
+ // D: Destination bytes, going to be copied from S bytes
444
+ // _: Uninvolved bytes in the writable section
445
+
330
446
let src = (
331
- self . buf . as_ptr ( ) . add ( self . head + start) . cast_const ( ) ,
332
- self . cap - self . head ,
447
+ self . buf . as_ptr ( ) . cast_const ( ) ,
448
+ // Src length - chunk 2 (see above diagram on the left)
449
+ self . tail ,
333
450
) ;
334
- let dst = ( self . buf . as_ptr ( ) . add ( self . tail ) , self . head - self . tail ) ;
335
- copy_bytes_overshooting ( src, dst, after_start) ;
336
-
337
- if after_start < len {
338
- let src = ( self . buf . as_ptr ( ) . cast_const ( ) , self . tail ) ;
339
- let dst = ( dst. 0 . add ( after_start) , dst. 1 - after_start) ;
340
- copy_bytes_overshooting ( src, dst, len - after_start) ;
341
- }
451
+
452
+ let dst = (
453
+ // SAFETY: we are still within the memory range of `buf`
454
+ unsafe { dst. 0 . add ( after_start) } ,
455
+ // Dst length (see above diagram)
456
+ dst. 1 - after_start,
457
+ ) ;
458
+
459
+ // SAFETY: `src` points at initialized data, `dst` points to writable memory
460
+ // and does not overlap `src`.
461
+ unsafe { copy_bytes_overshooting ( src, dst, len - after_start) }
342
462
}
343
463
}
344
464
}
0 commit comments