1use core::convert::TryInto;
4use core::fmt::Debug;
5
6pub trait Endianity: Debug + Default + Clone + Copy + PartialEq + Eq {
8 fn is_big_endian(self) -> bool;
10
11 #[inline]
13 fn is_little_endian(self) -> bool {
14 !self.is_big_endian()
15 }
16
17 #[inline]
23 fn read_u16(self, buf: &[u8]) -> u16 {
24 let bytes: &[u8; 2] = buf[..2].try_into().unwrap();
25 if self.is_big_endian() {
26 u16::from_be_bytes(*bytes)
27 } else {
28 u16::from_le_bytes(*bytes)
29 }
30 }
31
32 #[inline]
38 fn read_u32(self, buf: &[u8]) -> u32 {
39 let bytes: &[u8; 4] = buf[..4].try_into().unwrap();
40 if self.is_big_endian() {
41 u32::from_be_bytes(*bytes)
42 } else {
43 u32::from_le_bytes(*bytes)
44 }
45 }
46
47 #[inline]
53 fn read_u64(self, buf: &[u8]) -> u64 {
54 let bytes: &[u8; 8] = buf[..8].try_into().unwrap();
55 if self.is_big_endian() {
56 u64::from_be_bytes(*bytes)
57 } else {
58 u64::from_le_bytes(*bytes)
59 }
60 }
61
62 #[inline]
68 fn read_u128(self, buf: &[u8]) -> u128 {
69 let bytes: &[u8; 16] = buf[..16].try_into().unwrap();
70 if self.is_big_endian() {
71 u128::from_be_bytes(*bytes)
72 } else {
73 u128::from_le_bytes(*bytes)
74 }
75 }
76
77 #[inline]
83 fn read_uint(&mut self, buf: &[u8]) -> u64 {
84 let mut tmp = [0; 8];
85 if self.is_big_endian() {
86 tmp[8 - buf.len()..].copy_from_slice(buf);
87 } else {
88 tmp[..buf.len()].copy_from_slice(buf);
89 }
90 self.read_u64(&tmp)
91 }
92
93 #[inline]
99 fn read_i16(self, buf: &[u8]) -> i16 {
100 self.read_u16(buf) as i16
101 }
102
103 #[inline]
109 fn read_i32(self, buf: &[u8]) -> i32 {
110 self.read_u32(buf) as i32
111 }
112
113 #[inline]
119 fn read_i64(self, buf: &[u8]) -> i64 {
120 self.read_u64(buf) as i64
121 }
122
123 #[inline]
129 fn read_f32(self, buf: &[u8]) -> f32 {
130 f32::from_bits(self.read_u32(buf))
131 }
132
133 #[inline]
139 fn read_f64(self, buf: &[u8]) -> f64 {
140 f64::from_bits(self.read_u64(buf))
141 }
142
143 #[inline]
149 fn write_u16(self, buf: &mut [u8], n: u16) {
150 let bytes = if self.is_big_endian() {
151 n.to_be_bytes()
152 } else {
153 n.to_le_bytes()
154 };
155 buf[..2].copy_from_slice(&bytes);
156 }
157
158 #[inline]
164 fn write_u32(self, buf: &mut [u8], n: u32) {
165 let bytes = if self.is_big_endian() {
166 n.to_be_bytes()
167 } else {
168 n.to_le_bytes()
169 };
170 buf[..4].copy_from_slice(&bytes);
171 }
172
173 #[inline]
179 fn write_u64(self, buf: &mut [u8], n: u64) {
180 let bytes = if self.is_big_endian() {
181 n.to_be_bytes()
182 } else {
183 n.to_le_bytes()
184 };
185 buf[..8].copy_from_slice(&bytes);
186 }
187
188 #[inline]
194 fn write_u128(self, buf: &mut [u8], n: u128) {
195 let bytes = if self.is_big_endian() {
196 n.to_be_bytes()
197 } else {
198 n.to_le_bytes()
199 };
200 buf[..16].copy_from_slice(&bytes);
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
206pub enum RunTimeEndian {
207 Little,
209 Big,
211}
212
213impl Default for RunTimeEndian {
214 #[cfg(target_endian = "little")]
215 #[inline]
216 fn default() -> RunTimeEndian {
217 RunTimeEndian::Little
218 }
219
220 #[cfg(target_endian = "big")]
221 #[inline]
222 fn default() -> RunTimeEndian {
223 RunTimeEndian::Big
224 }
225}
226
227impl Endianity for RunTimeEndian {
228 #[inline]
229 fn is_big_endian(self) -> bool {
230 self != RunTimeEndian::Little
231 }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
236pub struct LittleEndian;
237
238impl Default for LittleEndian {
239 #[inline]
240 fn default() -> LittleEndian {
241 LittleEndian
242 }
243}
244
245impl Endianity for LittleEndian {
246 #[inline]
247 fn is_big_endian(self) -> bool {
248 false
249 }
250}
251
252#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
254pub struct BigEndian;
255
256impl Default for BigEndian {
257 #[inline]
258 fn default() -> BigEndian {
259 BigEndian
260 }
261}
262
263impl Endianity for BigEndian {
264 #[inline]
265 fn is_big_endian(self) -> bool {
266 true
267 }
268}
269
270#[cfg(target_endian = "little")]
272pub type NativeEndian = LittleEndian;
273
274#[cfg(target_endian = "little")]
275#[allow(non_upper_case_globals)]
276#[doc(hidden)]
277pub const NativeEndian: LittleEndian = LittleEndian;
278
279#[cfg(target_endian = "big")]
281pub type NativeEndian = BigEndian;
282
283#[cfg(target_endian = "big")]
284#[allow(non_upper_case_globals)]
285#[doc(hidden)]
286pub const NativeEndian: BigEndian = BigEndian;