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