whasm/grammar/core/byte.rs
1//! This module defines the deserialization of `whasm::grammar::Byte`.
2
3use super::*;
4
5/// Wrapper for a byte of information. It differs from an `u8` on how it is deserialized.
6/// A `Byte` reads exactly one byte from the input iterator, while a `u8` could potentially read
7/// several bytes (since unsigned integers are encoded using LEB-128).
8///
9/// A `Byte` takes exactly one byte of memory, and can be transmuted to `u8`.
10/// This is specially useful since it allows transmuting a vector of `Byte`s to a vector of `u8`.
11///
12/// # Example
13///
14/// ```
15/// # use whasm::grammar::*;
16/// let mut iter = [0x8E].iter().copied();
17/// let Byte(result) = deserialize(&mut iter).unwrap();
18/// assert_eq!(result, 0x8E);
19/// ```
20///
21/// Deserialization will return an error if the iterator is exhausted while deserializing.
22///
23/// ```
24/// # use whasm::grammar::*;
25/// let mut iter = [0x00].iter().copied();
26/// let Byte(_) = deserialize(&mut iter).unwrap();
27/// let result: Result<Byte> = deserialize(&mut iter);
28/// assert!(result.is_err());
29/// ```
30#[derive(Clone, Copy, Hash)]
31#[derive(Eq, PartialEq, Ord, PartialOrd)]
32pub struct Byte(pub u8);
33
34impl Grammar for Byte {
35 /// Read a `Byte` from an `Iterator<u8>`. It returns `Ok(Byte(_))` on success, and
36 /// `Error(Error::UnexpectedEndOfStream)` if the iterator returns `None`.
37 ///
38 /// Deserializing a `Byte` instead of using `iter.next()` is an easy way to convert the
39 /// `Option<u8>` returned by the iterator into a `Result<u8>` with a meaningful error type.
40 fn deserialize<Iter: Iterator<Item=u8>>(iter: &mut Iter) -> Result<Self> {
41 Ok(Byte(iter.next().ok_or(Error::UnexpectedEndOfStream)?))
42 }
43}
44
45impl std::fmt::Display for Byte {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "0x{:02X}", self.0)
48 }
49}
50
51impl std::fmt::Debug for Byte {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 write!(f, "0x{:02X}", self.0)
54 }
55}
56
57impl std::cmp::PartialEq<u8> for Byte {
58 fn eq(&self, other: &u8) -> bool {
59 self.0 == *other
60 }
61}
62
63impl std::cmp::PartialEq<char> for Byte {
64 fn eq(&self, other: &char) -> bool {
65 (self.0 as char) == *other
66 }
67}
68
69#[cfg(test)]
70mod test {
71 use crate as whasm;
72 use whasm::grammar::*;
73
74 #[test]
75 fn can_deserialize_byte() {
76 let mut iter = [0x8E].iter().copied();
77 let Byte(result) = deserialize(&mut iter).unwrap();
78 assert_eq!(result, 0x8E);
79 }
80
81 #[test]
82 fn byte_uses_exactly_1_byte() {
83 assert_eq!(std::mem::size_of::<Byte>(), 1);
84 }
85
86 #[test]
87 fn byte_transmutes_to_u8() {
88 let byte = Byte(42);
89 let transmuted: u8 = unsafe { std::mem::transmute(byte) };
90 assert_eq!(transmuted, 42);
91 }
92
93 #[test]
94 fn byte_vector_transmutes_to_u8_vector() {
95 let byte = vec![Byte(42), Byte(0x33), Byte(0x55)];
96 let transmuted: Vec<u8> = unsafe { std::mem::transmute(byte) };
97 assert_eq!(transmuted, vec![42, 0x33, 0x55]);
98 }
99}