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 a byte slice to a `Pod` type. |
25 | /// |
26 | /// Returns the type and the tail of the slice. |
27 | #[inline ] |
28 | pub 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 ] |
46 | pub 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 ] |
67 | pub 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 ] |
85 | pub 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 ] |
107 | pub 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 ] |
118 | pub 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 ] |
129 | pub 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 ] |
140 | pub 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 | |
149 | macro_rules! unsafe_impl_pod { |
150 | ($($struct_name:ident),+ $(,)?) => { |
151 | $( |
152 | unsafe impl Pod for $struct_name { } |
153 | )+ |
154 | } |
155 | } |
156 | |
157 | unsafe_impl_pod!(u8, u16, u32, u64); |
158 | |
159 | #[cfg (test)] |
160 | mod 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 | |