djin_protocol/
settings.rs

1use std::io::prelude::*;
2
3/// Defines serialization settings.
4#[derive(Clone, Debug, PartialEq, PartialOrd, Default)]
5pub struct Settings {
6    /// The byte ordering of data transmitted.
7    pub byte_order: ByteOrder,
8}
9
10/// Specifies the byte order of data transfer.
11///
12/// # `Eq` implementation
13///
14/// Here is a list of rules the `Eq` implementation satisfies.
15///
16///   * `LittleEndian == LittleEndian`
17///   * `LittleEndian != BigEndian`
18///   * `NativeEndian == LittleEndian` (but only on little endian machines)
19///   * `NativeEndian == BigEndian` (but only on big endian machines)
20///
21/// The `NativeEndian` byte order will successfully match against
22/// one of the two real-life byte orders.
23#[derive(Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
24pub enum ByteOrder {
25    /// Least significant byte first.
26    LittleEndian,
27    /// Most significant byte first.
28    BigEndian,
29    /// Whatever the byte ordering of the current machine is.
30    NativeEndian,
31}
32
33#[cfg(target_endian = "little")]
34const NATIVE_BYTE_ORDER: ByteOrder = ByteOrder::LittleEndian;
35#[cfg(target_endian = "big")]
36const NATIVE_BYTE_ORDER: ByteOrder = ByteOrder::BigEndian;
37
38impl ByteOrder {
39    /// Resolves the byte order into either little or big endian.
40    fn realize(self) -> Self {
41        match self {
42            ByteOrder::NativeEndian => NATIVE_BYTE_ORDER,
43            b => b,
44        }
45    }
46}
47
48impl Default for ByteOrder {
49    fn default() -> Self {
50        ByteOrder::BigEndian
51    }
52}
53
54impl ::std::cmp::PartialEq for ByteOrder {
55    fn eq(&self, other: &Self) -> bool {
56        use ByteOrder::*;
57
58        match (self.realize(), other.realize()) {
59            (LittleEndian, LittleEndian) => true,
60            (BigEndian, BigEndian) => true,
61            _ => false,
62        }
63    }
64}
65
66macro_rules! impl_byte_order_helpers {
67    ( $( $ty:ty => [ $read_name:ident : $write_name:ident ] )* ) => {
68        impl ByteOrder {
69            $(
70                pub fn $read_name(&self, read: &mut dyn Read) -> Result<$ty, crate::Error> {
71                    use byteorder as bo;
72
73                    Ok(match *self {
74                        ByteOrder::LittleEndian => bo::ReadBytesExt::$read_name::<bo::LittleEndian>(read),
75                        ByteOrder::BigEndian => bo::ReadBytesExt::$read_name::<bo::BigEndian>(read),
76                        ByteOrder::NativeEndian => bo::ReadBytesExt::$read_name::<bo::NativeEndian>(read),
77                    }?)
78                }
79
80                pub fn $write_name(&self, value: $ty,
81                                   write: &mut dyn Write) -> Result<(), crate::Error> {
82                    use byteorder as bo;
83
84                    Ok(match *self {
85                        ByteOrder::LittleEndian => bo::WriteBytesExt::$write_name::<bo::LittleEndian>(write, value),
86                        ByteOrder::BigEndian => bo::WriteBytesExt::$write_name::<bo::BigEndian>(write, value),
87                        ByteOrder::NativeEndian => bo::WriteBytesExt::$write_name::<bo::NativeEndian>(write, value),
88                    }?)
89                }
90            )*
91        }
92    };
93}
94
95impl_byte_order_helpers!(
96    u16 => [read_u16 : write_u16]
97    i16 => [read_i16 : write_i16]
98    u32 => [read_u32 : write_u32]
99    i32 => [read_i32 : write_i32]
100    u64 => [read_u64 : write_u64]
101    i64 => [read_i64 : write_i64]
102    f32 => [read_f32 : write_f32]
103    f64 => [read_f64 : write_f64]
104);
105