]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
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(not(all(feature = "read_core", feature = "write_core")), allow(dead_code))] | |
7 | ||
8 | use alloc::vec::Vec; | |
9 | use core::{fmt, mem, result, slice}; | |
10 | ||
11 | type Result<T> = result::Result<T, ()>; | |
12 | ||
13 | /// A trait for types that can safely be converted from and to byte slices. | |
14 | /// | |
15 | /// A type that is `Pod` must: | |
16 | /// - be `#[repr(C)]` or `#[repr(transparent)]` | |
17 | /// - have no invalid byte values | |
18 | /// - have no padding | |
19 | pub unsafe trait Pod: Copy + 'static {} | |
20 | ||
21 | /// Cast a byte slice to a `Pod` type. | |
22 | /// | |
23 | /// Returns the type and the tail of the slice. | |
24 | #[inline] | |
25 | pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> { | |
26 | let ptr = data.as_ptr(); | |
27 | if (ptr as usize) % mem::align_of::<T>() != 0 { | |
28 | return Err(()); | |
29 | } | |
30 | let size = mem::size_of::<T>(); | |
31 | let tail = data.get(size..).ok_or(())?; | |
32 | // Safety: | |
33 | // The alignment and size are checked by this function. | |
34 | // The Pod trait ensures the type is valid to cast from bytes. | |
35 | let val = unsafe { &*ptr.cast() }; | |
36 | Ok((val, tail)) | |
37 | } | |
38 | ||
39 | /// Cast a byte slice to a slice of a `Pod` type. | |
40 | /// | |
41 | /// Returns the type slice and the tail of the byte slice. | |
42 | #[inline] | |
43 | pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> { | |
44 | let ptr = data.as_ptr(); | |
45 | if (ptr as usize) % mem::align_of::<T>() != 0 { | |
46 | return Err(()); | |
47 | } | |
48 | let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?; | |
49 | let tail = data.get(size..).ok_or(())?; | |
50 | // Safety: | |
51 | // The alignment and size are checked by this function. | |
52 | // The Pod trait ensures the type is valid to cast from bytes. | |
53 | let slice = unsafe { slice::from_raw_parts(ptr.cast(), count) }; | |
54 | Ok((slice, tail)) | |
55 | } | |
56 | ||
57 | /// Cast a `Pod` type to a byte slice. | |
58 | #[inline] | |
59 | pub fn bytes_of<T: Pod>(val: &T) -> &[u8] { | |
60 | let size = mem::size_of::<T>(); | |
61 | // Safety: | |
62 | // Any alignment is allowed. | |
63 | // The size is determined in this function. | |
64 | // The Pod trait ensures the type is valid to cast to bytes. | |
65 | unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) } | |
66 | } | |
67 | ||
68 | /// A newtype for byte slices. | |
69 | /// | |
70 | /// It has these important features: | |
71 | /// - no methods that can panic, such as `Index` | |
72 | /// - convenience methods for `Pod` types | |
73 | /// - a useful `Debug` implementation | |
74 | #[derive(Default, Clone, Copy, PartialEq, Eq)] | |
75 | pub struct Bytes<'data>(pub &'data [u8]); | |
76 | ||
77 | impl<'data> fmt::Debug for Bytes<'data> { | |
78 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
79 | debug_list_bytes(self.0, fmt) | |
80 | } | |
81 | } | |
82 | ||
83 | impl<'data> Bytes<'data> { | |
84 | /// Return the length of the byte slice. | |
85 | #[inline] | |
86 | pub fn len(&self) -> usize { | |
87 | self.0.len() | |
88 | } | |
89 | ||
90 | /// Return true if the byte slice is empty. | |
91 | #[inline] | |
92 | pub fn is_empty(&self) -> bool { | |
93 | self.0.is_empty() | |
94 | } | |
95 | ||
96 | /// Skip over the given number of bytes at the start of the byte slice. | |
97 | /// | |
98 | /// Modifies the byte slice to start after the bytes. | |
99 | /// | |
100 | /// Returns an error if there are too few bytes. | |
101 | #[inline] | |
102 | pub fn skip(&mut self, offset: usize) -> Result<()> { | |
103 | match self.0.get(offset..) { | |
104 | Some(tail) => { | |
105 | self.0 = tail; | |
106 | Ok(()) | |
107 | } | |
108 | None => { | |
109 | self.0 = &[]; | |
110 | Err(()) | |
111 | } | |
112 | } | |
113 | } | |
114 | ||
115 | /// Return a reference to the given number of bytes at the start of the byte slice. | |
116 | /// | |
117 | /// Modifies the byte slice to start after the bytes. | |
118 | /// | |
119 | /// Returns an error if there are too few bytes. | |
120 | #[inline] | |
121 | pub fn read_bytes(&mut self, count: usize) -> Result<Bytes<'data>> { | |
122 | match (self.0.get(..count), self.0.get(count..)) { | |
123 | (Some(head), Some(tail)) => { | |
124 | self.0 = tail; | |
125 | Ok(Bytes(head)) | |
126 | } | |
127 | _ => { | |
128 | self.0 = &[]; | |
129 | Err(()) | |
130 | } | |
131 | } | |
132 | } | |
133 | ||
134 | /// Return a reference to the given number of bytes at the given offset of the byte slice. | |
135 | /// | |
136 | /// Returns an error if the offset is invalid or there are too few bytes. | |
137 | #[inline] | |
138 | pub fn read_bytes_at(mut self, offset: usize, count: usize) -> Result<Bytes<'data>> { | |
139 | self.skip(offset)?; | |
140 | self.read_bytes(count) | |
141 | } | |
142 | ||
143 | /// Return a reference to a `Pod` struct at the start of the byte slice. | |
144 | /// | |
145 | /// Modifies the byte slice to start after the bytes. | |
146 | /// | |
147 | /// Returns an error if there are too few bytes or the slice is incorrectly aligned. | |
148 | #[inline] | |
149 | pub fn read<T: Pod>(&mut self) -> Result<&'data T> { | |
150 | match from_bytes(self.0) { | |
151 | Ok((value, tail)) => { | |
152 | self.0 = tail; | |
153 | Ok(value) | |
154 | } | |
155 | Err(()) => { | |
156 | self.0 = &[]; | |
157 | Err(()) | |
158 | } | |
159 | } | |
160 | } | |
161 | ||
162 | /// Return a reference to a `Pod` struct at the given offset of the byte slice. | |
163 | /// | |
164 | /// Returns an error if there are too few bytes or the offset is incorrectly aligned. | |
165 | #[inline] | |
166 | pub fn read_at<T: Pod>(mut self, offset: usize) -> Result<&'data T> { | |
167 | self.skip(offset)?; | |
168 | self.read() | |
169 | } | |
170 | ||
171 | /// Return a reference to a slice of `Pod` structs at the start of the byte slice. | |
172 | /// | |
173 | /// Modifies the byte slice to start after the bytes. | |
174 | /// | |
175 | /// Returns an error if there are too few bytes or the offset is incorrectly aligned. | |
176 | #[inline] | |
177 | pub fn read_slice<T: Pod>(&mut self, count: usize) -> Result<&'data [T]> { | |
178 | match slice_from_bytes(self.0, count) { | |
179 | Ok((value, tail)) => { | |
180 | self.0 = tail; | |
181 | Ok(value) | |
182 | } | |
183 | Err(()) => { | |
184 | self.0 = &[]; | |
185 | Err(()) | |
186 | } | |
187 | } | |
188 | } | |
189 | ||
190 | /// Return a reference to a slice of `Pod` structs at the given offset of the byte slice. | |
191 | /// | |
192 | /// Returns an error if there are too few bytes or the offset is incorrectly aligned. | |
193 | #[inline] | |
194 | pub fn read_slice_at<T: Pod>(mut self, offset: usize, count: usize) -> Result<&'data [T]> { | |
195 | self.skip(offset)?; | |
196 | self.read_slice(count) | |
197 | } | |
198 | ||
199 | /// Read a null terminated string. | |
200 | /// | |
201 | /// Does not assume any encoding. | |
202 | /// Reads past the null byte, but doesn't return it. | |
203 | #[inline] | |
204 | pub fn read_string(&mut self) -> Result<&'data [u8]> { | |
205 | match self.0.iter().position(|&x| x == 0) { | |
206 | Some(null) => { | |
207 | // These will never fail. | |
208 | let bytes = self.read_bytes(null)?; | |
209 | self.skip(1)?; | |
210 | Ok(bytes.0) | |
211 | } | |
212 | None => { | |
213 | self.0 = &[]; | |
214 | Err(()) | |
215 | } | |
216 | } | |
217 | } | |
218 | ||
219 | /// Read a null terminated string at an offset. | |
220 | /// | |
221 | /// Does not assume any encoding. Does not return the null byte. | |
222 | #[inline] | |
223 | pub fn read_string_at(mut self, offset: usize) -> Result<&'data [u8]> { | |
224 | self.skip(offset)?; | |
225 | self.read_string() | |
226 | } | |
227 | } | |
228 | ||
fc512014 XL |
229 | /// Trait for writable buffer. |
230 | pub trait WritableBuffer { | |
231 | /// Returns position/offset for data to be written at. | |
232 | fn len(&self) -> usize; | |
233 | /// Returns true if buffer contains no data. | |
234 | fn is_empty(&self) -> bool; | |
235 | /// Reserves specified number of bytes in the buffer. | |
236 | fn reserve(&mut self, additional: usize) -> Result<()>; | |
237 | /// Resizes buffer to the specified length, fills new items | |
238 | /// with the specified value. | |
239 | fn resize(&mut self, new_len: usize, value: u8); | |
240 | /// Extends buffer with the specified slice of bytes. | |
241 | fn extend(&mut self, val: &[u8]); | |
242 | } | |
243 | ||
f035d41b XL |
244 | /// A newtype for byte vectors. |
245 | /// | |
246 | /// It provides convenience methods for `Pod` types. | |
247 | // TODO: should this be an extension trait for `Vec<u8>` instead? | |
248 | #[derive(Default, Clone, PartialEq, Eq)] | |
249 | pub(crate) struct BytesMut(pub Vec<u8>); | |
250 | ||
251 | impl fmt::Debug for BytesMut { | |
252 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
253 | debug_list_bytes(&self.0, fmt) | |
254 | } | |
255 | } | |
256 | ||
257 | impl BytesMut { | |
258 | #[inline] | |
259 | pub fn new() -> Self { | |
260 | BytesMut(Vec::new()) | |
261 | } | |
262 | ||
263 | #[inline] | |
fc512014 XL |
264 | pub fn write<T: Pod>(&mut self, val: &T) { |
265 | self.0.extend_from_slice(bytes_of(val)) | |
f035d41b XL |
266 | } |
267 | ||
268 | #[inline] | |
fc512014 XL |
269 | pub fn write_at<T: Pod>(&mut self, offset: usize, val: &T) -> Result<()> { |
270 | let src = bytes_of(val); | |
271 | let dest = self.0.get_mut(offset..).ok_or(())?; | |
272 | let dest = dest.get_mut(..src.len()).ok_or(())?; | |
273 | dest.copy_from_slice(src); | |
274 | Ok(()) | |
f035d41b XL |
275 | } |
276 | ||
277 | #[inline] | |
fc512014 XL |
278 | pub fn as_slice(&self) -> &[u8] { |
279 | self.0.as_slice() | |
f035d41b | 280 | } |
fc512014 | 281 | } |
f035d41b | 282 | |
fc512014 | 283 | impl WritableBuffer for BytesMut { |
f035d41b | 284 | #[inline] |
fc512014 XL |
285 | fn len(&self) -> usize { |
286 | self.0.len() | |
f035d41b XL |
287 | } |
288 | ||
289 | #[inline] | |
fc512014 XL |
290 | fn is_empty(&self) -> bool { |
291 | self.0.is_empty() | |
292 | } | |
293 | ||
294 | #[inline] | |
295 | fn reserve(&mut self, additional: usize) -> Result<()> { | |
296 | self.0.reserve(additional); | |
f035d41b XL |
297 | Ok(()) |
298 | } | |
299 | ||
300 | #[inline] | |
fc512014 XL |
301 | fn resize(&mut self, new_len: usize, value: u8) { |
302 | self.0.resize(new_len, value); | |
f035d41b XL |
303 | } |
304 | ||
305 | #[inline] | |
fc512014 | 306 | fn extend(&mut self, val: &[u8]) { |
f035d41b XL |
307 | self.0.extend_from_slice(val) |
308 | } | |
309 | } | |
310 | ||
311 | // Only for Debug impl of `Bytes/BytesMut`. | |
312 | fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
313 | let mut list = fmt.debug_list(); | |
314 | list.entries(bytes.iter().take(8).copied().map(DebugByte)); | |
315 | if bytes.len() > 8 { | |
316 | list.entry(&DebugLen(bytes.len())); | |
317 | } | |
318 | list.finish() | |
319 | } | |
320 | ||
321 | struct DebugByte(u8); | |
322 | ||
323 | impl fmt::Debug for DebugByte { | |
324 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
325 | write!(fmt, "0x{:02x}", self.0) | |
326 | } | |
327 | } | |
328 | ||
329 | struct DebugLen(usize); | |
330 | ||
331 | impl fmt::Debug for DebugLen { | |
332 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
333 | write!(fmt, "...; {}", self.0) | |
334 | } | |
335 | } | |
336 | ||
337 | macro_rules! unsafe_impl_pod { | |
338 | ($($struct_name:ident),+ $(,)?) => { | |
339 | $( | |
340 | unsafe impl Pod for $struct_name { } | |
341 | )+ | |
342 | } | |
343 | } | |
344 | ||
345 | unsafe_impl_pod!(u8, u16, u32, u64); | |
346 | ||
347 | #[cfg(test)] | |
348 | mod tests { | |
349 | use super::*; | |
350 | ||
351 | #[test] | |
352 | fn single() { | |
353 | let x = u32::to_be(0x0123_4567); | |
354 | let bytes = bytes_of(&x); | |
355 | assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]); | |
356 | ||
357 | let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)]; | |
358 | ||
359 | let (y, tail) = from_bytes::<u32>(bytes).unwrap(); | |
360 | assert_eq!(*y, x); | |
361 | assert_eq!(tail, &[]); | |
362 | ||
363 | let (y, tail) = from_bytes::<u16>(bytes).unwrap(); | |
364 | assert_eq!(*y, x16[0]); | |
365 | assert_eq!(tail, &bytes[2..]); | |
366 | ||
367 | let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap(); | |
368 | assert_eq!(*y, x16[1]); | |
369 | assert_eq!(tail, &[]); | |
370 | ||
371 | assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(())); | |
372 | assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(())); | |
373 | assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(())); | |
374 | } | |
375 | ||
376 | #[test] | |
377 | fn slice() { | |
378 | let x = u64::to_be(0x0123_4567_89ab_cdef); | |
379 | let bytes = bytes_of(&x); | |
380 | assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); | |
381 | ||
382 | let x16 = [ | |
383 | u16::to_be(0x0123), | |
384 | u16::to_be(0x4567), | |
385 | u16::to_be(0x89ab), | |
386 | u16::to_be(0xcdef), | |
387 | ]; | |
388 | ||
389 | let (y, tail) = slice_from_bytes::<u16>(&bytes, 4).unwrap(); | |
390 | assert_eq!(y, x16); | |
391 | assert_eq!(tail, &[]); | |
392 | ||
393 | let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap(); | |
394 | assert_eq!(y, &x16[1..3]); | |
395 | assert_eq!(tail, &bytes[6..]); | |
396 | ||
397 | assert_eq!(slice_from_bytes::<u16>(&bytes, 5), Err(())); | |
398 | assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(())); | |
399 | assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(())); | |
400 | } | |
401 | ||
402 | #[test] | |
403 | fn bytes() { | |
404 | let x = u32::to_be(0x0123_4567); | |
405 | let data = Bytes(bytes_of(&x)); | |
406 | ||
407 | let mut bytes = data; | |
408 | assert_eq!(bytes.skip(0), Ok(())); | |
409 | assert_eq!(bytes, data); | |
410 | ||
411 | let mut bytes = data; | |
412 | assert_eq!(bytes.skip(4), Ok(())); | |
413 | assert_eq!(bytes, Bytes(&[])); | |
414 | ||
415 | let mut bytes = data; | |
416 | assert_eq!(bytes.skip(5), Err(())); | |
417 | assert_eq!(bytes, Bytes(&[])); | |
418 | ||
419 | let mut bytes = data; | |
420 | assert_eq!(bytes.read_bytes(0), Ok(Bytes(&[]))); | |
421 | assert_eq!(bytes, data); | |
422 | ||
423 | let mut bytes = data; | |
424 | assert_eq!(bytes.read_bytes(4), Ok(data)); | |
425 | assert_eq!(bytes, Bytes(&[])); | |
426 | ||
427 | let mut bytes = data; | |
428 | assert_eq!(bytes.read_bytes(5), Err(())); | |
429 | assert_eq!(bytes, Bytes(&[])); | |
430 | ||
431 | assert_eq!(data.read_bytes_at(0, 0), Ok(Bytes(&[]))); | |
432 | assert_eq!(data.read_bytes_at(4, 0), Ok(Bytes(&[]))); | |
433 | assert_eq!(data.read_bytes_at(0, 4), Ok(data)); | |
434 | assert_eq!(data.read_bytes_at(1, 4), Err(())); | |
435 | ||
436 | let mut bytes = data; | |
437 | assert_eq!(bytes.read::<u16>(), Ok(&u16::to_be(0x0123))); | |
438 | assert_eq!(bytes, Bytes(&[0x45, 0x67])); | |
439 | assert_eq!(data.read_at::<u16>(2), Ok(&u16::to_be(0x4567))); | |
440 | assert_eq!(data.read_at::<u16>(3), Err(())); | |
441 | assert_eq!(data.read_at::<u16>(4), Err(())); | |
442 | ||
443 | let mut bytes = data; | |
444 | assert_eq!(bytes.read::<u32>(), Ok(&x)); | |
445 | assert_eq!(bytes, Bytes(&[])); | |
446 | ||
447 | let mut bytes = data; | |
448 | assert_eq!(bytes.read::<u64>(), Err(())); | |
449 | assert_eq!(bytes, Bytes(&[])); | |
450 | ||
451 | let mut bytes = data; | |
452 | assert_eq!(bytes.read_slice::<u8>(0), Ok(&[][..])); | |
453 | assert_eq!(bytes, data); | |
454 | ||
455 | let mut bytes = data; | |
456 | assert_eq!(bytes.read_slice::<u8>(4), Ok(data.0)); | |
457 | assert_eq!(bytes, Bytes(&[])); | |
458 | ||
459 | let mut bytes = data; | |
460 | assert_eq!(bytes.read_slice::<u8>(5), Err(())); | |
461 | assert_eq!(bytes, Bytes(&[])); | |
462 | ||
463 | assert_eq!(data.read_slice_at::<u8>(0, 0), Ok(&[][..])); | |
464 | assert_eq!(data.read_slice_at::<u8>(4, 0), Ok(&[][..])); | |
465 | assert_eq!(data.read_slice_at::<u8>(0, 4), Ok(data.0)); | |
466 | assert_eq!(data.read_slice_at::<u8>(1, 4), Err(())); | |
467 | ||
468 | let data = Bytes(&[0x01, 0x02, 0x00, 0x04]); | |
469 | ||
470 | let mut bytes = data; | |
471 | assert_eq!(bytes.read_string(), Ok(&data.0[..2])); | |
472 | assert_eq!(bytes.0, &data.0[3..]); | |
473 | ||
474 | let mut bytes = data; | |
475 | bytes.skip(3).unwrap(); | |
476 | assert_eq!(bytes.read_string(), Err(())); | |
477 | assert_eq!(bytes.0, &[]); | |
478 | ||
479 | assert_eq!(data.read_string_at(0), Ok(&data.0[..2])); | |
480 | assert_eq!(data.read_string_at(1), Ok(&data.0[1..2])); | |
481 | assert_eq!(data.read_string_at(2), Ok(&[][..])); | |
482 | assert_eq!(data.read_string_at(3), Err(())); | |
483 | } | |
484 | ||
485 | #[test] | |
486 | fn bytes_mut() { | |
487 | let data = BytesMut(vec![0x01, 0x23, 0x45, 0x67]); | |
488 | ||
489 | let mut bytes = data.clone(); | |
490 | bytes.write(&u16::to_be(0x89ab)); | |
491 | assert_eq!(bytes.0, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]); | |
492 | ||
493 | let mut bytes = data.clone(); | |
494 | assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(())); | |
495 | assert_eq!(bytes.0, [0x89, 0xab, 0x45, 0x67]); | |
496 | ||
497 | let mut bytes = data.clone(); | |
498 | assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(())); | |
499 | assert_eq!(bytes.0, [0x01, 0x23, 0x89, 0xab]); | |
500 | ||
501 | assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(())); | |
502 | assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(())); | |
503 | assert_eq!( | |
504 | BytesMut::default().write_at(0, &u32::to_be(0x89ab)), | |
505 | Err(()) | |
506 | ); | |
507 | } | |
508 | ||
509 | #[test] | |
510 | fn bytes_debug() { | |
511 | assert_eq!(format!("{:?}", Bytes(&[])), "[]"); | |
512 | assert_eq!(format!("{:?}", Bytes(&[0x01])), "[0x01]"); | |
513 | assert_eq!( | |
514 | format!( | |
515 | "{:?}", | |
516 | Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]) | |
517 | ), | |
518 | "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]" | |
519 | ); | |
520 | assert_eq!( | |
521 | format!( | |
522 | "{:?}", | |
523 | Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]) | |
524 | ), | |
525 | "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]" | |
526 | ); | |
527 | ||
528 | assert_eq!(format!("{:?}", BytesMut(vec![])), "[]"); | |
529 | assert_eq!( | |
530 | format!( | |
531 | "{:?}", | |
532 | BytesMut(vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]) | |
533 | ), | |
534 | "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]" | |
535 | ); | |
536 | } | |
537 | } |