copy_nonoverlapping

Function copy_nonoverlapping 

Source
pub unsafe fn copy_nonoverlapping(src: BitPtr, dst: BitPtrMut, bit_count: usize)
Expand description

Copies bit_count bits from src to dst. The source and destination must not overlap.

bitptr does not provide a copy function for memory which might overlap.

The copy is “untyped” in the sense that data may be uninitialized. The initialization state is preserved exactly.

§Safety

Behavior is undefined if any of the following conditions are violated:

  • src.floor_byte() must be valid for reads of ((src.subbyte_bit().get() as usize) + bit_count).div_ceil(8) bytes.
  • dst.floor_byte() must be valid for writes of ((dst.subbyte_bit().get() as usize) + bit_count).div_ceil(8) bytes.
  • The region of memory beginning at src with a size of bit_count bits must not overlap with the region of memory beginning at dst with the same size. The byte region may overlap. The relevant bits themselves may not.

§Footguns

Make sure to account for endianness.

#![cfg(not(target_endian = "big"))]

use bitptr::{ BitPtr, BitPtrMut };

let     x = 0b_0101101110010110_u16;
//                    ^^^^^^^ This is the region that is 'supposed to' be read.
let mut y = 0b_1111111111111111_u16;
//                ^^^^^^^ This is the region that is 'supposed to' be written.

let xptr = unsafe { BitPtr::new_with_offset(&x as *const _ as *const _, 7) };
let yptr = unsafe { BitPtrMut::new_with_offset(&mut y as *mut _ as *mut _, 3) };

unsafe { bitptr::copy_nonoverlapping(xptr, yptr, 7); }
assert_eq!(y, 0b_1111100101111111_u16);

On a little-endian system, the assert_eq! in the code above will panic. The final value of y is 0b_1011111111100101_u16, not 0b_1111100101111111_u16.

Explicitely converting from native-endian to big-endian before, and big-endian to native-endian after, can solve this issue.

use bitptr::{ BitPtr, BitPtrMut };

let     x = 0b_0101101110010110_u16.to_be();
//                    ^^^^^^^ This is the region that is 'supposed to' be read.
let mut y = 0b_1111111111111111_u16.to_be();
//                ^^^^^^^ This is the region that is 'supposed to' be written.

let xptr = unsafe { BitPtr::new_with_offset(&x as *const _ as *const _, 7) };
let yptr = unsafe { BitPtrMut::new_with_offset(&mut y as *mut _ as *mut _, 3) };

unsafe { bitptr::copy_nonoverlapping(xptr, yptr, 7); }
assert_eq!(u16::from_be(y), 0b_1111100101111111_u16);

Analagous to ptr::copy_nonoverlapping.