1#![cfg_attr(
7 not(all(feature = "read_core", feature = "write_core")),
8 allow(dead_code)
9)]
10
11use core::{mem, result, slice};
12
13type Result<T> = result::Result<T, ()>;
14
15pub unsafe trait Pod: Copy + 'static {}
23
24#[inline]
30pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> {
31 let size = mem::size_of::<T>();
32 let tail = data.get(size..).ok_or(())?;
33 let ptr = data.as_ptr();
34 if (ptr as usize) % mem::align_of::<T>() != 0 {
35 return Err(());
36 }
37 let val = unsafe { &*ptr.cast() };
41 Ok((val, tail))
42}
43
44#[inline]
50pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> {
51 let size = mem::size_of::<T>();
52 if size > data.len() {
53 return Err(());
54 }
55 let (data, tail) = data.split_at_mut(size);
56 let ptr = data.as_mut_ptr();
57 if (ptr as usize) % mem::align_of::<T>() != 0 {
58 return Err(());
59 }
60 let val = unsafe { &mut *ptr.cast() };
64 Ok((val, tail))
65}
66
67#[inline]
73pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> {
74 let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
75 let tail = data.get(size..).ok_or(())?;
76 let ptr = data.as_ptr();
77 if (ptr as usize) % mem::align_of::<T>() != 0 {
78 return Err(());
79 }
80 let slice = unsafe { slice::from_raw_parts(ptr.cast(), count) };
84 Ok((slice, tail))
85}
86
87#[inline]
93pub fn slice_from_bytes_mut<T: Pod>(
94 data: &mut [u8],
95 count: usize,
96) -> Result<(&mut [T], &mut [u8])> {
97 let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
98 if size > data.len() {
99 return Err(());
100 }
101 let (data, tail) = data.split_at_mut(size);
102 let ptr = data.as_mut_ptr();
103 if (ptr as usize) % mem::align_of::<T>() != 0 {
104 return Err(());
105 }
106 let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), count) };
110 Ok((slice, tail))
111}
112
113#[inline]
120pub fn slice_from_all_bytes<T: Pod>(data: &[u8]) -> Result<&[T]> {
121 let count = data.len() / mem::size_of::<T>();
122 let (slice, tail) = slice_from_bytes(data, count)?;
123 if !tail.is_empty() {
124 return Err(());
125 }
126 Ok(slice)
127}
128
129#[inline]
136pub fn slice_from_all_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<&mut [T]> {
137 let count = data.len() / mem::size_of::<T>();
138 let (slice, tail) = slice_from_bytes_mut(data, count)?;
139 if !tail.is_empty() {
140 return Err(());
141 }
142 Ok(slice)
143}
144
145#[inline]
147pub fn bytes_of<T: Pod>(val: &T) -> &[u8] {
148 let size = mem::size_of::<T>();
149 unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) }
154}
155
156#[inline]
158pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] {
159 let size = mem::size_of::<T>();
160 unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) }
165}
166
167#[inline]
169pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
170 let size = val.len().wrapping_mul(mem::size_of::<T>());
171 unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) }
176}
177
178#[inline]
180pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] {
181 let size = val.len().wrapping_mul(mem::size_of::<T>());
182 unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) }
187}
188
189macro_rules! unsafe_impl_pod {
190 ($($struct_name:ident),+ $(,)?) => {
191 $(
192 unsafe impl Pod for $struct_name { }
193 )+
194 }
195}
196
197unsafe_impl_pod!(u8, u16, u32, u64);
198
199unsafe impl<const N: usize, T: Pod> Pod for [T; N] {}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn single() {
207 let x = u32::to_be(0x0123_4567);
208 let mut x_mut = x;
209 let bytes = bytes_of(&x);
210 let bytes_mut = bytes_of_mut(&mut x_mut);
211 assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]);
212 assert_eq!(bytes, bytes_mut);
213
214 let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)];
215
216 let (y, tail) = from_bytes::<u32>(bytes).unwrap();
217 let (y_mut, tail_mut) = from_bytes_mut::<u32>(bytes_mut).unwrap();
218 assert_eq!(*y, x);
219 assert_eq!(y, y_mut);
220 assert_eq!(tail, &[]);
221 assert_eq!(tail, tail_mut);
222
223 let (y, tail) = from_bytes::<u16>(bytes).unwrap();
224 let (y_mut, tail_mut) = from_bytes_mut::<u16>(bytes_mut).unwrap();
225 assert_eq!(*y, x16[0]);
226 assert_eq!(y, y_mut);
227 assert_eq!(tail, &bytes[2..]);
228 assert_eq!(tail, tail_mut);
229
230 let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap();
231 let (y_mut, tail_mut) = from_bytes_mut::<u16>(&mut bytes_mut[2..]).unwrap();
232 assert_eq!(*y, x16[1]);
233 assert_eq!(y, y_mut);
234 assert_eq!(tail, &[]);
235 assert_eq!(tail, tail_mut);
236
237 assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(()));
238 assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(()));
239 assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(()));
240 assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[1..]), Err(()));
241 assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[3..]), Err(()));
242 assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[4..]), Err(()));
243 }
244
245 #[test]
246 fn slice() {
247 let x = [
248 u16::to_be(0x0123),
249 u16::to_be(0x4567),
250 u16::to_be(0x89ab),
251 u16::to_be(0xcdef),
252 ];
253 let mut x_mut = x;
254
255 let bytes = bytes_of_slice(&x);
256 let bytes_mut = bytes_of_slice_mut(&mut x_mut);
257 assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
258 assert_eq!(bytes, bytes_mut);
259
260 let (y, tail) = slice_from_bytes::<u16>(bytes, 4).unwrap();
261 let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(bytes_mut, 4).unwrap();
262 assert_eq!(y, x);
263 assert_eq!(y, y_mut);
264 assert_eq!(tail, &[]);
265 assert_eq!(tail, tail_mut);
266
267 let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap();
268 let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 2).unwrap();
269 assert_eq!(y, &x[1..3]);
270 assert_eq!(y, y_mut);
271 assert_eq!(tail, &bytes[6..]);
272 assert_eq!(tail, tail_mut);
273
274 assert_eq!(slice_from_bytes::<u16>(bytes, 5), Err(()));
275 assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(()));
276 assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(()));
277 assert_eq!(slice_from_bytes_mut::<u16>(bytes_mut, 5), Err(()));
278 assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(()));
279 assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(()));
280 }
281}