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 | |
11 | use core::{mem, result, slice}; |
12 | |
13 | type 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 |
22 | pub unsafe trait Pod: Copy + 'static {} |
23 | |
24 | /// Cast the head of a byte slice to a `Pod` type. |
25 | /// |
26 | /// Returns the type and the tail of the byte slice. |
27 | /// |
28 | /// Returns an error if the byte slice is too short or the alignment is invalid. |
29 | #[inline ] |
30 | pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> { |
31 | let size: usize = mem::size_of::<T>(); |
32 | let tail: &[u8] = data.get(size..).ok_or(())?; |
33 | let ptr: *const u8 = data.as_ptr(); |
34 | if (ptr as usize) % mem::align_of::<T>() != 0 { |
35 | return Err(()); |
36 | } |
37 | // Safety: |
38 | // The alignment and size are checked by this function. |
39 | // The Pod trait ensures the type is valid to cast from bytes. |
40 | let val: &T = unsafe { &*ptr.cast() }; |
41 | Ok((val, tail)) |
42 | } |
43 | |
44 | /// Cast the head of a mutable byte slice to a `Pod` type. |
45 | /// |
46 | /// Returns the type and the tail of the byte slice. |
47 | /// |
48 | /// Returns an error if the byte slice is too short or the alignment is invalid. |
49 | #[inline ] |
50 | pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> { |
51 | let size: usize = mem::size_of::<T>(); |
52 | if size > data.len() { |
53 | return Err(()); |
54 | } |
55 | let (data: &mut [u8], tail: &mut [u8]) = data.split_at_mut(mid:size); |
56 | let ptr: *mut u8 = data.as_mut_ptr(); |
57 | if (ptr as usize) % mem::align_of::<T>() != 0 { |
58 | return Err(()); |
59 | } |
60 | // Safety: |
61 | // The alignment and size are checked by this function. |
62 | // The Pod trait ensures the type is valid to cast from bytes. |
63 | let val: &mut {unknown} = unsafe { &mut *ptr.cast() }; |
64 | Ok((val, tail)) |
65 | } |
66 | |
67 | /// Cast the head of a byte slice to a slice of a `Pod` type. |
68 | /// |
69 | /// Returns the type slice and the tail of the byte slice. |
70 | /// |
71 | /// Returns an error if the byte slice is too short or the alignment is invalid. |
72 | #[inline ] |
73 | pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> { |
74 | let size: usize = count.checked_mul(mem::size_of::<T>()).ok_or(())?; |
75 | let tail: &[u8] = data.get(size..).ok_or(())?; |
76 | let ptr: *const u8 = data.as_ptr(); |
77 | if (ptr as usize) % mem::align_of::<T>() != 0 { |
78 | return Err(()); |
79 | } |
80 | // Safety: |
81 | // The alignment and size are checked by this function. |
82 | // The Pod trait ensures the type is valid to cast from bytes. |
83 | let slice: &[T] = unsafe { slice::from_raw_parts(data:ptr.cast(), len:count) }; |
84 | Ok((slice, tail)) |
85 | } |
86 | |
87 | /// Cast the head of a mutable byte slice to a slice of a `Pod` type. |
88 | /// |
89 | /// Returns the type slice and the tail of the byte slice. |
90 | /// |
91 | /// Returns an error if the byte slice is too short or the alignment is invalid. |
92 | #[inline ] |
93 | pub fn slice_from_bytes_mut<T: Pod>( |
94 | data: &mut [u8], |
95 | count: usize, |
96 | ) -> Result<(&mut [T], &mut [u8])> { |
97 | let size: usize = count.checked_mul(mem::size_of::<T>()).ok_or(())?; |
98 | if size > data.len() { |
99 | return Err(()); |
100 | } |
101 | let (data: &mut [u8], tail: &mut [u8]) = data.split_at_mut(mid:size); |
102 | let ptr: *mut u8 = data.as_mut_ptr(); |
103 | if (ptr as usize) % mem::align_of::<T>() != 0 { |
104 | return Err(()); |
105 | } |
106 | // Safety: |
107 | // The alignment and size are checked by this function. |
108 | // The Pod trait ensures the type is valid to cast from bytes. |
109 | let slice: &mut [T] = unsafe { slice::from_raw_parts_mut(data:ptr.cast(), len:count) }; |
110 | Ok((slice, tail)) |
111 | } |
112 | |
113 | /// Cast all of a byte slice to a slice of a `Pod` type. |
114 | /// |
115 | /// Returns the type slice. |
116 | /// |
117 | /// Returns an error if the size of the byte slice is not an exact multiple |
118 | /// of the type size, or the alignment is invalid. |
119 | #[inline ] |
120 | pub fn slice_from_all_bytes<T: Pod>(data: &[u8]) -> Result<&[T]> { |
121 | let count: usize = data.len() / mem::size_of::<T>(); |
122 | let (slice: &[T], tail: &[u8]) = slice_from_bytes(data, count)?; |
123 | if !tail.is_empty() { |
124 | return Err(()); |
125 | } |
126 | Ok(slice) |
127 | } |
128 | |
129 | /// Cast all of a byte slice to a slice of a `Pod` type. |
130 | /// |
131 | /// Returns the type slice. |
132 | /// |
133 | /// Returns an error if the size of the byte slice is not an exact multiple |
134 | /// of the type size, or the alignment is invalid. |
135 | #[inline ] |
136 | pub fn slice_from_all_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<&mut [T]> { |
137 | let count: usize = data.len() / mem::size_of::<T>(); |
138 | let (slice: &mut [T], tail: &mut [u8]) = slice_from_bytes_mut(data, count)?; |
139 | if !tail.is_empty() { |
140 | return Err(()); |
141 | } |
142 | Ok(slice) |
143 | } |
144 | |
145 | /// Cast a `Pod` type to a byte slice. |
146 | #[inline ] |
147 | pub fn bytes_of<T: Pod>(val: &T) -> &[u8] { |
148 | let size: usize = mem::size_of::<T>(); |
149 | // Safety: |
150 | // Any alignment is allowed. |
151 | // The size is determined in this function. |
152 | // The Pod trait ensures the type is valid to cast to bytes. |
153 | unsafe { slice::from_raw_parts(data:slice::from_ref(val).as_ptr().cast(), len:size) } |
154 | } |
155 | |
156 | /// Cast a `Pod` type to a mutable byte slice. |
157 | #[inline ] |
158 | pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] { |
159 | let size: usize = mem::size_of::<T>(); |
160 | // Safety: |
161 | // Any alignment is allowed. |
162 | // The size is determined in this function. |
163 | // The Pod trait ensures the type is valid to cast to bytes. |
164 | unsafe { slice::from_raw_parts_mut(data:slice::from_mut(val).as_mut_ptr().cast(), len:size) } |
165 | } |
166 | |
167 | /// Cast a slice of a `Pod` type to a byte slice. |
168 | #[inline ] |
169 | pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] { |
170 | let size: usize = val.len().wrapping_mul(mem::size_of::<T>()); |
171 | // Safety: |
172 | // Any alignment is allowed. |
173 | // The size is determined in this function. |
174 | // The Pod trait ensures the type is valid to cast to bytes. |
175 | unsafe { slice::from_raw_parts(data:val.as_ptr().cast(), len:size) } |
176 | } |
177 | |
178 | /// Cast a slice of a `Pod` type to a mutable byte slice. |
179 | #[inline ] |
180 | pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] { |
181 | let size: usize = val.len().wrapping_mul(mem::size_of::<T>()); |
182 | // Safety: |
183 | // Any alignment is allowed. |
184 | // The size is determined in this function. |
185 | // The Pod trait ensures the type is valid to cast to bytes. |
186 | unsafe { slice::from_raw_parts_mut(data:val.as_mut_ptr().cast(), len:size) } |
187 | } |
188 | |
189 | macro_rules! unsafe_impl_pod { |
190 | ($($struct_name:ident),+ $(,)?) => { |
191 | $( |
192 | unsafe impl Pod for $struct_name { } |
193 | )+ |
194 | } |
195 | } |
196 | |
197 | unsafe_impl_pod!(u8, u16, u32, u64); |
198 | |
199 | unsafe impl<const N: usize, T: Pod> Pod for [T; N] {} |
200 | |
201 | #[cfg (test)] |
202 | mod 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 | } |
282 | |