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/// # Safety
18/// A type that is `Pod` must:
19/// - be `#[repr(C)]` or `#[repr(transparent)]`
20/// - have no invalid byte values
21/// - have no padding
22pub unsafe trait Pod: Copy + 'static {}
23
24/// Cast a byte slice to a `Pod` type.
25///
26/// Returns the type and the tail of the slice.
27#[inline]
28pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> {
29 let size: usize = mem::size_of::<T>();
30 let tail: &[u8] = data.get(size..).ok_or(())?;
31 let ptr: *const u8 = data.as_ptr();
32 if (ptr as usize) % mem::align_of::<T>() != 0 {
33 return Err(());
34 }
35 // Safety:
36 // The alignment and size are checked by this function.
37 // The Pod trait ensures the type is valid to cast from bytes.
38 let val: &T = unsafe { &*ptr.cast() };
39 Ok((val, tail))
40}
41
42/// Cast a mutable byte slice to a `Pod` type.
43///
44/// Returns the type and the tail of the slice.
45#[inline]
46pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> {
47 let size: usize = mem::size_of::<T>();
48 if size > data.len() {
49 return Err(());
50 }
51 let (data: &mut [u8], tail: &mut [u8]) = data.split_at_mut(mid:size);
52 let ptr: *mut u8 = data.as_mut_ptr();
53 if (ptr as usize) % mem::align_of::<T>() != 0 {
54 return Err(());
55 }
56 // Safety:
57 // The alignment and size are checked by this function.
58 // The Pod trait ensures the type is valid to cast from bytes.
59 let val: &mut T = unsafe { &mut *ptr.cast() };
60 Ok((val, tail))
61}
62
63/// Cast a byte slice to a slice of a `Pod` type.
64///
65/// Returns the type slice and the tail of the byte slice.
66#[inline]
67pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> {
68 let size: usize = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
69 let tail: &[u8] = data.get(size..).ok_or(())?;
70 let ptr: *const u8 = data.as_ptr();
71 if (ptr as usize) % mem::align_of::<T>() != 0 {
72 return Err(());
73 }
74 // Safety:
75 // The alignment and size are checked by this function.
76 // The Pod trait ensures the type is valid to cast from bytes.
77 let slice: &[T] = unsafe { slice::from_raw_parts(data:ptr.cast(), len:count) };
78 Ok((slice, tail))
79}
80
81/// Cast a mutable byte slice to a slice of a `Pod` type.
82///
83/// Returns the type slice and the tail of the byte slice.
84#[inline]
85pub fn slice_from_bytes_mut<T: Pod>(
86 data: &mut [u8],
87 count: usize,
88) -> Result<(&mut [T], &mut [u8])> {
89 let size: usize = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
90 if size > data.len() {
91 return Err(());
92 }
93 let (data: &mut [u8], tail: &mut [u8]) = data.split_at_mut(mid:size);
94 let ptr: *mut u8 = data.as_mut_ptr();
95 if (ptr as usize) % mem::align_of::<T>() != 0 {
96 return Err(());
97 }
98 // Safety:
99 // The alignment and size are checked by this function.
100 // The Pod trait ensures the type is valid to cast from bytes.
101 let slice: &mut [T] = unsafe { slice::from_raw_parts_mut(data:ptr.cast(), len:count) };
102 Ok((slice, tail))
103}
104
105/// Cast a `Pod` type to a byte slice.
106#[inline]
107pub fn bytes_of<T: Pod>(val: &T) -> &[u8] {
108 let size: usize = mem::size_of::<T>();
109 // Safety:
110 // Any alignment is allowed.
111 // The size is determined in this function.
112 // The Pod trait ensures the type is valid to cast to bytes.
113 unsafe { slice::from_raw_parts(data:slice::from_ref(val).as_ptr().cast(), len:size) }
114}
115
116/// Cast a `Pod` type to a mutable byte slice.
117#[inline]
118pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] {
119 let size: usize = mem::size_of::<T>();
120 // Safety:
121 // Any alignment is allowed.
122 // The size is determined in this function.
123 // The Pod trait ensures the type is valid to cast to bytes.
124 unsafe { slice::from_raw_parts_mut(data:slice::from_mut(val).as_mut_ptr().cast(), len:size) }
125}
126
127/// Cast a slice of a `Pod` type to a byte slice.
128#[inline]
129pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
130 let size: usize = val.len().wrapping_mul(mem::size_of::<T>());
131 // Safety:
132 // Any alignment is allowed.
133 // The size is determined in this function.
134 // The Pod trait ensures the type is valid to cast to bytes.
135 unsafe { slice::from_raw_parts(data:val.as_ptr().cast(), len:size) }
136}
137
138/// Cast a slice of a `Pod` type to a mutable byte slice.
139#[inline]
140pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] {
141 let size: usize = val.len().wrapping_mul(mem::size_of::<T>());
142 // Safety:
143 // Any alignment is allowed.
144 // The size is determined in this function.
145 // The Pod trait ensures the type is valid to cast to bytes.
146 unsafe { slice::from_raw_parts_mut(data:val.as_mut_ptr().cast(), len:size) }
147}
148
149macro_rules! unsafe_impl_pod {
150 ($($struct_name:ident),+ $(,)?) => {
151 $(
152 unsafe impl Pod for $struct_name { }
153 )+
154 }
155}
156
157unsafe_impl_pod!(u8, u16, u32, u64);
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn single() {
165 let x = u32::to_be(0x0123_4567);
166 let mut x_mut = x;
167 let bytes = bytes_of(&x);
168 let bytes_mut = bytes_of_mut(&mut x_mut);
169 assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]);
170 assert_eq!(bytes, bytes_mut);
171
172 let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)];
173
174 let (y, tail) = from_bytes::<u32>(bytes).unwrap();
175 let (y_mut, tail_mut) = from_bytes_mut::<u32>(bytes_mut).unwrap();
176 assert_eq!(*y, x);
177 assert_eq!(y, y_mut);
178 assert_eq!(tail, &[]);
179 assert_eq!(tail, tail_mut);
180
181 let (y, tail) = from_bytes::<u16>(bytes).unwrap();
182 let (y_mut, tail_mut) = from_bytes_mut::<u16>(bytes_mut).unwrap();
183 assert_eq!(*y, x16[0]);
184 assert_eq!(y, y_mut);
185 assert_eq!(tail, &bytes[2..]);
186 assert_eq!(tail, tail_mut);
187
188 let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap();
189 let (y_mut, tail_mut) = from_bytes_mut::<u16>(&mut bytes_mut[2..]).unwrap();
190 assert_eq!(*y, x16[1]);
191 assert_eq!(y, y_mut);
192 assert_eq!(tail, &[]);
193 assert_eq!(tail, tail_mut);
194
195 assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(()));
196 assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(()));
197 assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(()));
198 assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[1..]), Err(()));
199 assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[3..]), Err(()));
200 assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[4..]), Err(()));
201 }
202
203 #[test]
204 fn slice() {
205 let x = [
206 u16::to_be(0x0123),
207 u16::to_be(0x4567),
208 u16::to_be(0x89ab),
209 u16::to_be(0xcdef),
210 ];
211 let mut x_mut = x;
212
213 let bytes = bytes_of_slice(&x);
214 let bytes_mut = bytes_of_slice_mut(&mut x_mut);
215 assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
216 assert_eq!(bytes, bytes_mut);
217
218 let (y, tail) = slice_from_bytes::<u16>(bytes, 4).unwrap();
219 let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(bytes_mut, 4).unwrap();
220 assert_eq!(y, x);
221 assert_eq!(y, y_mut);
222 assert_eq!(tail, &[]);
223 assert_eq!(tail, tail_mut);
224
225 let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap();
226 let (y_mut, tail_mut) = slice_from_bytes::<u16>(&mut bytes_mut[2..], 2).unwrap();
227 assert_eq!(y, &x[1..3]);
228 assert_eq!(y, y_mut);
229 assert_eq!(tail, &bytes[6..]);
230 assert_eq!(tail, tail_mut);
231
232 assert_eq!(slice_from_bytes::<u16>(bytes, 5), Err(()));
233 assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(()));
234 assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(()));
235 assert_eq!(slice_from_bytes_mut::<u16>(bytes_mut, 5), Err(()));
236 assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(()));
237 assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(()));
238 }
239}
240