1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::io::{Read, Result, Write};

use crate::Endian;

macro_rules! decl_read_method {
    ($type:ty, $method:ident) => {
        #[doc = concat!("Read a `", stringify!($type), "`.")]
        fn $method(&mut self, endian: Endian) -> Result<$type>;
    };
}

/// A trait for reading bytes.
///
/// This is implemented for all types that implement [`Read`].
pub trait ReadBytes {
    decl_read_method!(u8, read_u8);
    decl_read_method!(u16, read_u16);
    decl_read_method!(u32, read_u32);
    decl_read_method!(u64, read_u64);
    decl_read_method!(u128, read_u128);

    decl_read_method!(i8, read_i8);
    decl_read_method!(i16, read_i16);
    decl_read_method!(i32, read_i32);
    decl_read_method!(i64, read_i64);
    decl_read_method!(i128, read_i128);

    decl_read_method!(f32, read_f32);
    decl_read_method!(f64, read_f64);
}

macro_rules! impl_read_method {
    ($type:ty, $method:ident, $size:literal) => {
        #[inline]
        fn $method(&mut self, endian: Endian) -> Result<$type> {
            let mut buf = [0; $size];
            self.read_exact(&mut buf)?;
            Ok(endian.$method(&buf))
        }
    };
}

impl<R: Read> ReadBytes for R {
    impl_read_method!(u8, read_u8, 1);
    impl_read_method!(u16, read_u16, 2);
    impl_read_method!(u32, read_u32, 4);
    impl_read_method!(u64, read_u64, 8);
    impl_read_method!(u128, read_u128, 16);

    impl_read_method!(i8, read_i8, 1);
    impl_read_method!(i16, read_i16, 2);
    impl_read_method!(i32, read_i32, 4);
    impl_read_method!(i64, read_i64, 8);
    impl_read_method!(i128, read_i128, 16);

    impl_read_method!(f32, read_f32, 4);
    impl_read_method!(f64, read_f64, 8);
}

macro_rules! decl_write_method {
    ($type:ty, $method:ident) => {
        #[doc = concat!("Write a `", stringify!($type), "`.")]
        fn $method(&mut self, endian: Endian, n: $type) -> Result<()>;
    };
}

/// A trait for writing bytes.
///
/// This is implemented for all types that implement [`Write`].
pub trait WriteBytes {
    decl_write_method!(u8, write_u8);
    decl_write_method!(u16, write_u16);
    decl_write_method!(u32, write_u32);
    decl_write_method!(u64, write_u64);
    decl_write_method!(u128, write_u128);

    decl_write_method!(i8, write_i8);
    decl_write_method!(i16, write_i16);
    decl_write_method!(i32, write_i32);
    decl_write_method!(i64, write_i64);
    decl_write_method!(i128, write_i128);

    decl_write_method!(f32, write_f32);
    decl_write_method!(f64, write_f64);
}

macro_rules! impl_write_method {
    ($type:ty, $method:ident, $size:literal) => {
        #[inline]
        fn $method(&mut self, endian: Endian, n: $type) -> Result<()> {
            let mut buf = [0; $size];
            endian.$method(&mut buf, n);
            self.write_all(&buf)
        }
    };
}

impl<W: Write> WriteBytes for W {
    impl_write_method!(u8, write_u8, 1);
    impl_write_method!(u16, write_u16, 2);
    impl_write_method!(u32, write_u32, 4);
    impl_write_method!(u64, write_u64, 8);
    impl_write_method!(u128, write_u128, 16);

    impl_write_method!(i8, write_i8, 1);
    impl_write_method!(i16, write_i16, 2);
    impl_write_method!(i32, write_i32, 4);
    impl_write_method!(i64, write_i64, 8);
    impl_write_method!(i128, write_i128, 16);

    impl_write_method!(f32, write_f32, 4);
    impl_write_method!(f64, write_f64, 8);
}