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}