Skip to main content

object/
pod.rs

1//! Tools for converting file format structures to and from bytes.
2//!
3//! This module should be replaced once rust provides safe transmutes.
4
5// This module provides functions for both read and write features.
6#![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
15/// A trait for types that can safely be converted from and to byte slices.
16///
17/// Note: `Pod` is implemented for `[T; 0]`, but this isn't useful in practice
18/// and may be removed or become a compile-time error in future.
19///
20/// # Safety
21/// A type that is `Pod` must:
22/// - be `#[repr(C)]` or `#[repr(transparent)]`
23/// - have no invalid byte values
24/// - have no padding
25pub unsafe trait Pod: Copy + 'static {}
26
27/// Cast the head of a byte slice to a `Pod` type.
28///
29/// Returns the type and the tail of the byte slice.
30///
31/// Returns an error if the byte slice is too short or the alignment is invalid.
32#[inline]
33pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> {
34    let size = mem::size_of::<T>();
35    let tail = data.get(size..).ok_or(())?;
36    let ptr = data.as_ptr();
37    if (ptr as usize) % mem::align_of::<T>() != 0 {
38        return Err(());
39    }
40    // Safety:
41    // The alignment and size are checked by this function.
42    // The Pod trait ensures the type is valid to cast from bytes.
43    let val = unsafe { &*ptr.cast() };
44    Ok((val, tail))
45}
46
47/// Cast the head of a mutable byte slice to a `Pod` type.
48///
49/// Returns the type and the tail of the byte slice.
50///
51/// Returns an error if the byte slice is too short or the alignment is invalid.
52#[inline]
53pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> {
54    let size = mem::size_of::<T>();
55    if size > data.len() {
56        return Err(());
57    }
58    let (data, tail) = data.split_at_mut(size);
59    let ptr = data.as_mut_ptr();
60    if (ptr as usize) % mem::align_of::<T>() != 0 {
61        return Err(());
62    }
63    // Safety:
64    // The alignment and size are checked by this function.
65    // The Pod trait ensures the type is valid to cast from bytes.
66    let val = unsafe { &mut *ptr.cast() };
67    Ok((val, tail))
68}
69
70/// Cast the head of a byte slice to a slice of a `Pod` type.
71///
72/// Returns the type slice and the tail of the byte slice.
73///
74/// Returns an error if the byte slice is too short or the alignment is invalid.
75#[inline]
76pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> {
77    let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
78    let tail = data.get(size..).ok_or(())?;
79    let ptr = data.as_ptr();
80    if (ptr as usize) % mem::align_of::<T>() != 0 {
81        return Err(());
82    }
83    // Safety:
84    // The alignment and size are checked by this function.
85    // The Pod trait ensures the type is valid to cast from bytes.
86    let slice = unsafe { slice::from_raw_parts(ptr.cast(), count) };
87    Ok((slice, tail))
88}
89
90/// Cast the head of a mutable byte slice to a slice of a `Pod` type.
91///
92/// Returns the type slice and the tail of the byte slice.
93///
94/// Returns an error if the byte slice is too short or the alignment is invalid.
95#[inline]
96pub fn slice_from_bytes_mut<T: Pod>(
97    data: &mut [u8],
98    count: usize,
99) -> Result<(&mut [T], &mut [u8])> {
100    let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
101    if size > data.len() {
102        return Err(());
103    }
104    let (data, tail) = data.split_at_mut(size);
105    let ptr = data.as_mut_ptr();
106    if (ptr as usize) % mem::align_of::<T>() != 0 {
107        return Err(());
108    }
109    // Safety:
110    // The alignment and size are checked by this function.
111    // The Pod trait ensures the type is valid to cast from bytes.
112    let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), count) };
113    Ok((slice, tail))
114}
115
116/// Cast all of a byte slice to a slice of a `Pod` type.
117///
118/// Returns the type slice.
119///
120/// Returns an error if the size of the byte slice is not an exact multiple
121/// of the type size, or the alignment is invalid.
122#[inline]
123pub fn slice_from_all_bytes<T: Pod>(data: &[u8]) -> Result<&[T]> {
124    // TODO: change to compile time assert when MSRV allows.
125    let size = mem::size_of::<T>();
126    if size == 0 {
127        return Err(());
128    }
129    let count = data.len() / size;
130    let (slice, tail) = slice_from_bytes(data, count)?;
131    if !tail.is_empty() {
132        return Err(());
133    }
134    Ok(slice)
135}
136
137/// Cast all of a byte slice to a slice of a `Pod` type.
138///
139/// Returns the type slice.
140///
141/// Returns an error if the size of the byte slice is not an exact multiple
142/// of the type size, or the alignment is invalid.
143#[inline]
144pub fn slice_from_all_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<&mut [T]> {
145    // TODO: change to compile time assert when MSRV allows.
146    let size = mem::size_of::<T>();
147    if size == 0 {
148        return Err(());
149    }
150    let count = data.len() / size;
151    let (slice, tail) = slice_from_bytes_mut(data, count)?;
152    if !tail.is_empty() {
153        return Err(());
154    }
155    Ok(slice)
156}
157
158/// Cast a `Pod` type to a byte slice.
159#[inline]
160pub fn bytes_of<T: Pod>(val: &T) -> &[u8] {
161    let size = mem::size_of::<T>();
162    // Safety:
163    // Any alignment is allowed.
164    // The size is determined in this function.
165    // The Pod trait ensures the type is valid to cast to bytes.
166    unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) }
167}
168
169/// Cast a `Pod` type to a mutable byte slice.
170#[inline]
171pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] {
172    let size = mem::size_of::<T>();
173    // Safety:
174    // Any alignment is allowed.
175    // The size is determined in this function.
176    // The Pod trait ensures the type is valid to cast to bytes.
177    unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) }
178}
179
180/// Cast a slice of a `Pod` type to a byte slice.
181#[inline]
182pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
183    let size = val.len().wrapping_mul(mem::size_of::<T>());
184    // Safety:
185    // Any alignment is allowed.
186    // The size is determined in this function.
187    // The Pod trait ensures the type is valid to cast to bytes.
188    unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) }
189}
190
191/// Cast a slice of a `Pod` type to a mutable byte slice.
192#[inline]
193pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] {
194    let size = val.len().wrapping_mul(mem::size_of::<T>());
195    // Safety:
196    // Any alignment is allowed.
197    // The size is determined in this function.
198    // The Pod trait ensures the type is valid to cast to bytes.
199    unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) }
200}
201
202macro_rules! unsafe_impl_pod {
203    ($($struct_name:ident),+ $(,)?) => {
204        $(
205            unsafe impl Pod for $struct_name { }
206        )+
207    }
208}
209
210unsafe_impl_pod!(u8, u16, u32, u64);
211
212unsafe impl<const N: usize, T: Pod> Pod for [T; N] {}
213
214#[cfg(test)]
215mod tests {
216    use super::*;
217
218    #[test]
219    fn single() {
220        let x = u32::to_be(0x0123_4567);
221        let mut x_mut = x;
222        let bytes = bytes_of(&x);
223        let bytes_mut = bytes_of_mut(&mut x_mut);
224        assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]);
225        assert_eq!(bytes, bytes_mut);
226
227        let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)];
228
229        let (y, tail) = from_bytes::<u32>(bytes).unwrap();
230        let (y_mut, tail_mut) = from_bytes_mut::<u32>(bytes_mut).unwrap();
231        assert_eq!(*y, x);
232        assert_eq!(y, y_mut);
233        assert_eq!(tail, &[]);
234        assert_eq!(tail, tail_mut);
235
236        let (y, tail) = from_bytes::<u16>(bytes).unwrap();
237        let (y_mut, tail_mut) = from_bytes_mut::<u16>(bytes_mut).unwrap();
238        assert_eq!(*y, x16[0]);
239        assert_eq!(y, y_mut);
240        assert_eq!(tail, &bytes[2..]);
241        assert_eq!(tail, tail_mut);
242
243        let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap();
244        let (y_mut, tail_mut) = from_bytes_mut::<u16>(&mut bytes_mut[2..]).unwrap();
245        assert_eq!(*y, x16[1]);
246        assert_eq!(y, y_mut);
247        assert_eq!(tail, &[]);
248        assert_eq!(tail, tail_mut);
249
250        assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(()));
251        assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(()));
252        assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(()));
253        assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[1..]), Err(()));
254        assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[3..]), Err(()));
255        assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[4..]), Err(()));
256    }
257
258    #[test]
259    fn slice() {
260        let x = [
261            u16::to_be(0x0123),
262            u16::to_be(0x4567),
263            u16::to_be(0x89ab),
264            u16::to_be(0xcdef),
265        ];
266        let mut x_mut = x;
267
268        let bytes = bytes_of_slice(&x);
269        let bytes_mut = bytes_of_slice_mut(&mut x_mut);
270        assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
271        assert_eq!(bytes, bytes_mut);
272
273        let (y, tail) = slice_from_bytes::<u16>(bytes, 4).unwrap();
274        let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(bytes_mut, 4).unwrap();
275        assert_eq!(y, x);
276        assert_eq!(y, y_mut);
277        assert_eq!(tail, &[]);
278        assert_eq!(tail, tail_mut);
279
280        let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap();
281        let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 2).unwrap();
282        assert_eq!(y, &x[1..3]);
283        assert_eq!(y, y_mut);
284        assert_eq!(tail, &bytes[6..]);
285        assert_eq!(tail, tail_mut);
286
287        assert_eq!(slice_from_bytes::<u16>(bytes, 5), Err(()));
288        assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(()));
289        assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(()));
290        assert_eq!(slice_from_bytes_mut::<u16>(bytes_mut, 5), Err(()));
291        assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(()));
292        assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(()));
293    }
294
295    #[test]
296    fn slice_zero() {
297        assert_eq!(slice_from_all_bytes::<[u8; 0]>(&[]), Err(()));
298        assert_eq!(slice_from_all_bytes_mut::<[u8; 0]>(&mut []), Err(()));
299    }
300}