1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
//! A tiny crate, which provides slices to the memory which backs an instance of a struct.
//!
//! ```
//! use as_bytes::AsBytes;
//! let i = u32::MAX;
//! let bytes = unsafe { i.as_bytes() };
//! assert_eq!(bytes, [255, 255, 255, 255]);
//! ```
//! You can use this to peek at structure layout.
//! One usecase is for testing sending structs sent the wire.
//! The below examples demonstrate two different packing attributes on the same structure.
//! ```
//! # #[repr(packed)]
//! # #[allow(dead_code)] // unread fields
//! # struct ReprPacked {
//! # a: usize,
//! # b: u8,
//! # c: usize,
//! # }
//! # use as_bytes::AsBytes;
//!
//! let packed = ReprPacked {
//! a: usize::MAX,
//! b: 0u8,
//! c: usize::MAX,
//! };
//! let bytes = unsafe { packed.as_bytes() };
//! assert_eq!(
//! bytes,
//! [255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255]
//! );
//! ```
//!
//! ```
//! # #[repr(C)]
//! # struct ReprC {
//! # a: usize,
//! # b: u8,
//! # c: usize,
//! # }
//! # use as_bytes::AsBytes;
//!
//! let packed = ReprC {
//! a: usize::MAX,
//! b: 0u8,
//! c: usize::MAX,
//! };
//! let bytes = unsafe { packed.as_bytes() };
//! assert_eq!(
//! bytes,
//! [
//! 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255
//! ]
//! );
//! ```
/// Return a slice of the memory that contains the struct
pub trait AsBytes {
unsafe fn as_bytes(&self) -> &[u8] {
let ptr = self as *const _ as *const u8;
let len = std::mem::size_of_val(self);
std::slice::from_raw_parts(ptr, len)
}
unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
let ptr = self as *mut _ as *mut u8;
let len = std::mem::size_of_val(self);
std::slice::from_raw_parts_mut(ptr, len)
}
}
impl<T> AsBytes for T {}
#[cfg(test)]
mod tests {
use crate::AsBytes;
#[test]
fn test_u32() {
let i = u32::MAX;
let bytes = unsafe { i.as_bytes() };
assert_eq!(bytes, [255, 255, 255, 255]);
}
#[repr(packed)]
#[allow(dead_code)] // unread fields
struct ReprPacked {
a: usize,
b: u8,
c: usize,
}
#[test]
fn test_repr_packed_struct() {
let packed = ReprPacked {
a: usize::MAX,
b: 0u8,
c: usize::MAX,
};
let bytes = unsafe { packed.as_bytes() };
assert_eq!(
bytes,
[255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255]
)
}
#[repr(C)]
struct ReprC {
a: usize,
b: u8,
c: usize,
}
#[test]
fn test_repr_c_struct() {
let packed = ReprC {
a: usize::MAX,
b: 0u8,
c: usize::MAX,
};
let bytes = unsafe { packed.as_bytes() };
assert_eq!(
bytes,
[
255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255,
255, 255, 255, 255
]
)
}
}