Skip to content

Commit

Permalink
Merge pull request gimli-rs#297 from philipc/issue-294
Browse files Browse the repository at this point in the history
pod: add bytes_of_mut and bytes_of_slice_mut
  • Loading branch information
philipc committed May 4, 2021
2 parents e6ea28e + 365a142 commit 0c2bbf2
Showing 1 changed file with 52 additions and 2 deletions.
54 changes: 52 additions & 2 deletions src/pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,17 @@ pub fn bytes_of<T: Pod>(val: &T) -> &[u8] {
unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) }
}

/// Cast a `Pod` type to a mutable byte slice.
#[inline]
pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] {
let size = mem::size_of::<T>();
// Safety:
// Any alignment is allowed.
// The size is determined in this function.
// The Pod trait ensures the type is valid to cast to bytes.
unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) }
}

/// Cast a slice of a `Pod` type to a byte slice.
#[inline]
pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
Expand All @@ -125,6 +136,17 @@ pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) }
}

/// Cast a slice of a `Pod` type to a mutable byte slice.
#[inline]
pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] {
let size = val.len().wrapping_mul(mem::size_of::<T>());
// Safety:
// Any alignment is allowed.
// The size is determined in this function.
// The Pod trait ensures the type is valid to cast to bytes.
unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) }
}

/// A newtype for byte slices.
///
/// It has these important features:
Expand Down Expand Up @@ -425,26 +447,41 @@ mod tests {
#[test]
fn single() {
let x = u32::to_be(0x0123_4567);
let mut x_mut = x;
let bytes = bytes_of(&x);
let bytes_mut = bytes_of_mut(&mut x_mut);
assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]);
assert_eq!(bytes, bytes_mut);

let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)];

let (y, tail) = from_bytes::<u32>(bytes).unwrap();
let (y_mut, tail_mut) = from_bytes_mut::<u32>(bytes_mut).unwrap();
assert_eq!(*y, x);
assert_eq!(y, y_mut);
assert_eq!(tail, &[]);
assert_eq!(tail, tail_mut);

let (y, tail) = from_bytes::<u16>(bytes).unwrap();
let (y_mut, tail_mut) = from_bytes_mut::<u16>(bytes_mut).unwrap();
assert_eq!(*y, x16[0]);
assert_eq!(y, y_mut);
assert_eq!(tail, &bytes[2..]);
assert_eq!(tail, tail_mut);

let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap();
let (y_mut, tail_mut) = from_bytes_mut::<u16>(&mut bytes_mut[2..]).unwrap();
assert_eq!(*y, x16[1]);
assert_eq!(y, y_mut);
assert_eq!(tail, &[]);
assert_eq!(tail, tail_mut);

assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(()));
assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(()));
assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(()));
assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[1..]), Err(()));
assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[3..]), Err(()));
assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[4..]), Err(()));
}

#[test]
Expand All @@ -455,20 +492,33 @@ mod tests {
u16::to_be(0x89ab),
u16::to_be(0xcdef),
];
let mut x_mut = x;

let bytes = bytes_of_slice(&x);
let bytes_mut = bytes_of_slice_mut(&mut x_mut);
assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
assert_eq!(bytes, bytes_mut);

let (y, tail) = slice_from_bytes::<u16>(&bytes, 4).unwrap();
let (y, tail) = slice_from_bytes::<u16>(bytes, 4).unwrap();
let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(bytes_mut, 4).unwrap();
assert_eq!(y, x);
assert_eq!(y, y_mut);
assert_eq!(tail, &[]);
assert_eq!(tail, tail_mut);

let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap();
let (y_mut, tail_mut) = slice_from_bytes::<u16>(&mut bytes_mut[2..], 2).unwrap();
assert_eq!(y, &x[1..3]);
assert_eq!(y, y_mut);
assert_eq!(tail, &bytes[6..]);
assert_eq!(tail, tail_mut);

assert_eq!(slice_from_bytes::<u16>(&bytes, 5), Err(()));
assert_eq!(slice_from_bytes::<u16>(bytes, 5), Err(()));
assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(()));
assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(()));
assert_eq!(slice_from_bytes_mut::<u16>(bytes_mut, 5), Err(()));
assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(()));
assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(()));
}

#[test]
Expand Down

0 comments on commit 0c2bbf2

Please sign in to comment.