musli_binary_common/int/
traits.rs

1use core::ops::{BitAnd, BitXor, Neg, Shl, Shr};
2
3use crate::int::ByteOrder;
4use crate::reader::Reader;
5use crate::writer::Writer;
6
7/// Trait that encodes common behaviors of unsigned numbers.
8pub trait Unsigned:
9    Sized
10    + Copy
11    + Shr<u32, Output = Self>
12    + Shl<u32, Output = Self>
13    + BitXor<Self, Output = Self>
14    + BitAnd<Self, Output = Self>
15    + PartialOrd<Self>
16    + Ord
17{
18    /// The number `1` as represented by the current unsigned number.
19    const ONE: Self;
20
21    /// Number of bytes.
22    const BYTES: u8;
23
24    /// The signed representation of this unsigned number.
25    type Signed: Signed;
26
27    /// Coerce this number bitwise into its signed representation.
28    fn signed(self) -> Self::Signed;
29
30    /// Construct from the first byte.
31    fn from_byte(byte: u8) -> Self;
32
33    /// Coerce into the lowest 8-bits as a byte.
34    fn as_byte(self) -> u8;
35
36    /// Test if this value is smaller than the specified byte.
37    fn is_smaller_than(self, byte: u8) -> bool;
38
39    /// Test if value is zero.
40    fn is_zero(self) -> bool;
41
42    /// Perform a shift-right operation.
43    fn checked_shr(self, value: u32) -> Option<Self>;
44
45    /// Perform a shift-left operation.
46    fn checked_shl(self, value: u32) -> Option<Self>;
47
48    /// Perform a checked addition.
49    fn checked_add(self, value: Self) -> Option<Self>;
50}
51
52/// Helper trait for performing I/O over [Unsigned] types.
53pub trait ByteOrderIo: Unsigned {
54    /// Write the current byte array to the given writer in little-endian
55    /// encoding.
56    fn write_bytes<W, B>(self, writer: W) -> Result<(), W::Error>
57    where
58        W: Writer,
59        B: ByteOrder;
60
61    /// Read the current value from the reader in little-endian encoding.
62    fn read_bytes<'de, R, B>(reader: R) -> Result<Self, R::Error>
63    where
64        R: Reader<'de>,
65        B: ByteOrder;
66}
67
68/// Trait that encodes common behaviors of signed numbers.
69pub trait Signed:
70    Sized
71    + Copy
72    + Neg<Output = Self>
73    + Shr<u32, Output = Self>
74    + Shl<u32, Output = Self>
75    + BitXor<Self, Output = Self>
76{
77    /// The number of bits in this signed number.
78    const BITS: u32;
79
80    /// The unsigned representation of this number.
81    type Unsigned: Unsigned;
82
83    /// Coerce this number bitwise into its unsigned representation.
84    fn unsigned(self) -> Self::Unsigned;
85}
86
87macro_rules! implement {
88    ($signed:ty, $unsigned:ty, $type_flag:expr) => {
89        impl Signed for $signed {
90            const BITS: u32 = <$signed>::BITS;
91
92            type Unsigned = $unsigned;
93
94            fn unsigned(self) -> Self::Unsigned {
95                self as $unsigned
96            }
97        }
98
99        impl Unsigned for $unsigned {
100            const ONE: Self = 1;
101            const BYTES: u8 = (<$unsigned>::BITS / 8) as u8;
102
103            type Signed = $signed;
104
105            #[inline]
106            fn signed(self) -> Self::Signed {
107                self as $signed
108            }
109
110            #[inline]
111            fn from_byte(byte: u8) -> Self {
112                byte as $unsigned
113            }
114
115            #[inline]
116            fn as_byte(self) -> u8 {
117                self as u8
118            }
119
120            #[inline]
121            fn is_smaller_than(self, b: u8) -> bool {
122                self < b as $unsigned
123            }
124
125            #[inline]
126            fn is_zero(self) -> bool {
127                self == 0
128            }
129
130            #[inline]
131            fn checked_shr(self, value: u32) -> Option<Self> {
132                self.checked_shr(value)
133            }
134
135            #[inline]
136            fn checked_shl(self, value: u32) -> Option<Self> {
137                self.checked_shl(value)
138            }
139
140            #[inline]
141            fn checked_add(self, value: Self) -> Option<Self> {
142                self.checked_add(value)
143            }
144        }
145    };
146}
147
148macro_rules! implement_io {
149    ($signed:ty, $unsigned:ty, $type_flag:expr, $read:ident, $write:ident) => {
150        implement!($signed, $unsigned, $type_flag);
151
152        impl ByteOrderIo for $unsigned {
153            #[inline]
154            fn write_bytes<W, B>(self, mut writer: W) -> Result<(), W::Error>
155            where
156                W: Writer,
157                B: ByteOrder,
158            {
159                writer.write_array(B::$write(self))
160            }
161
162            #[inline]
163            fn read_bytes<'de, R, B>(mut reader: R) -> Result<Self, R::Error>
164            where
165                R: Reader<'de>,
166                B: ByteOrder,
167            {
168                Ok(B::$read(reader.read_array()?))
169            }
170        }
171    };
172}
173
174implement_io!(i16, u16, Fixed16, read_u16, write_u16);
175implement_io!(i32, u32, Fixed32, read_u32, write_u32);
176implement_io!(i64, u64, Fixed64, read_u64, write_u64);
177implement_io!(i128, u128, Fixed128, read_u128, write_u128);
178implement!(isize, usize, Fixed32);