read_primitives/
lib.rs

1/*!
2read-primitives provides traits to read primitive types from any type that implements [`std::io::Read`](https://doc.rust-lang.org/std/io/trait.Read.html)
3
4 # Examples
5
6```
7    use read_primitives::ReadF64;
8    let bytes: [u8; 8] = [24, 45, 68, 84, 251, 33, 9, 64];
9    let float = bytes.as_slice().read_le_f64().unwrap();
10    assert_eq!(std::f64::consts::PI, float)
11```
12*/
13
14use std::io::{self, Read};
15
16macro_rules! impl_traits {
17    ($($type:ty),+) => {
18        $(
19            ::paste::paste!{
20                #[doc = "Trait to read "$type "."]
21                #[doc = "# Errors"]
22                #[doc = "errors exactly when [`Read::read_exact`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact) errors"]
23                pub trait [<Read $type:camel>]: Read {
24                    #[doc = "Read " $type "in native byte order"]
25                    fn [<read_ne_  $type>](&mut self) -> io::Result<$type> {
26                        let mut bytes = [0u8; std::mem::size_of::<$type>()];
27                        self.read_exact(&mut bytes)?;
28                        Ok($type::from_ne_bytes(bytes))
29                    }
30                    #[doc = "Read " $type "in little endian byte order"]
31                    #[doc = "# Errors"]
32                    #[doc = "errors exactly when [`Read::read_exact`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact) errors"]
33                    fn [<read_le_  $type>](&mut self) -> io::Result<$type> {
34                        let mut bytes = [0u8; std::mem::size_of::<$type>()];
35                        self.read_exact(&mut bytes)?;
36                        Ok($type::from_le_bytes(bytes))
37                    }
38                    #[doc = "Read " $type "in big endian byte order"]
39                    #[doc = "# Errors"]
40                    #[doc = "errors exactly when [`Read::read_exact`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact) errors"]
41                    fn [<read_be_  $type>](&mut self) -> io::Result<$type> {
42                        let mut bytes = [0u8; std::mem::size_of::<$type>()];
43                        self.read_exact(&mut bytes)?;
44                        Ok($type::from_be_bytes(bytes))
45                    }
46                }
47                impl<T:Read> [<Read $type:camel>] for T{}
48            }
49        )+
50    };
51}
52
53impl_traits!(u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64);
54
55/// Trait to read u8
56pub trait ReadU8: Read {
57    /// Read a u8
58    /// # Errors
59    /// errors exactly when [`Read::read_exact`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact) errors
60    fn read_u8(&mut self) -> io::Result<u8> {
61        let mut bytes = [0u8; 1];
62        self.read_exact(&mut bytes)?;
63        Ok(u8::from_ne_bytes(bytes))
64    }
65}
66impl<R> ReadU8 for R where R: Read {}
67
68/// Trait to read char
69pub trait ReadChar: Read {
70    /// Read a char
71    ///  It is a assumed that the char is represented in native byte order
72    /// # Errors
73    /// errors exactly when [`Read::read_exact`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact) errors
74    fn read_char(&mut self) -> io::Result<Option<char>> {
75        let mut bytes = [0u8; 4];
76        self.read_exact(&mut bytes)?;
77        Ok(char::from_u32(u32::from_ne_bytes(bytes)))
78    }
79}
80impl<R> ReadChar for R where R: Read {}
81
82/// Trait to read bool
83pub trait ReadBool: Read {
84    /// Read a bool
85    /// # Errors
86    /// errors exactly when [`Read::read_exact`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact) errors
87    fn read_bool(&mut self) -> io::Result<bool> {
88        let mut bytes = [0u8; 1];
89        self.read_exact(&mut bytes)?;
90        Ok(u8::from_ne_bytes(bytes) != 0)
91    }
92}
93impl<R> ReadBool for R where R: Read {}
94
95#[cfg(test)]
96mod test {
97    use crate::*;
98
99    macro_rules! impl_tests {
100        ($($type:ty),+) => {
101            $(
102                ::paste::paste! {
103                    #[test]
104                    fn [<read_ne_ $type>]() {
105                        let bytes = [<37 $type>].to_ne_bytes();
106                        let number = bytes.as_slice().[<read_ne_ $type>]().unwrap();
107                        assert_eq!([<37 $type>], number)
108                    }
109                }
110                ::paste::paste! {
111                    #[test]
112                    fn [<read_le_ $type>]() {
113                        let bytes = [<37 $type>].to_le_bytes();
114                        let number = bytes.as_slice().[<read_le_ $type>]().unwrap();
115                        assert_eq!([<37 $type>], number)
116                    }
117                }
118                ::paste::paste! {
119                    #[test]
120                    fn [<read_be_ $type>]() {
121                        let bytes = [<37 $type>].to_be_bytes();
122                        let number = bytes.as_slice().[<read_be_ $type>]().unwrap();
123                        assert_eq!([<37 $type>], number)
124                    }
125                }
126            )+
127        };
128    }
129    impl_tests!(u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64);
130
131    #[test]
132    fn read_u8() {
133        let bytes = 37u8.to_ne_bytes();
134        let byte = bytes.as_slice().read_u8().unwrap();
135        assert_eq!(37, byte)
136    }
137}