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_uint(&mut self, buf: &[u8]) -> u64 {
69 let mut tmp = [0; 8];
70 if self.is_big_endian() {
71 tmp[8 - buf.len()..].copy_from_slice(buf);
72 } else {
73 tmp[..buf.len()].copy_from_slice(buf);
74 }
75 self.read_u64(&tmp)
76 }
77
78 #[inline]
84 fn read_i16(self, buf: &[u8]) -> i16 {
85 self.read_u16(buf) as i16
86 }
87
88 #[inline]
94 fn read_i32(self, buf: &[u8]) -> i32 {
95 self.read_u32(buf) as i32
96 }
97
98 #[inline]
104 fn read_i64(self, buf: &[u8]) -> i64 {
105 self.read_u64(buf) as i64
106 }
107
108 #[inline]
114 fn read_f32(self, buf: &[u8]) -> f32 {
115 f32::from_bits(self.read_u32(buf))
116 }
117
118 #[inline]
124 fn read_f64(self, buf: &[u8]) -> f64 {
125 f64::from_bits(self.read_u64(buf))
126 }
127
128 #[inline]
134 fn write_u16(self, buf: &mut [u8], n: u16) {
135 let bytes = if self.is_big_endian() {
136 n.to_be_bytes()
137 } else {
138 n.to_le_bytes()
139 };
140 buf[..2].copy_from_slice(&bytes);
141 }
142
143 #[inline]
149 fn write_u32(self, buf: &mut [u8], n: u32) {
150 let bytes = if self.is_big_endian() {
151 n.to_be_bytes()
152 } else {
153 n.to_le_bytes()
154 };
155 buf[..4].copy_from_slice(&bytes);
156 }
157
158 #[inline]
164 fn write_u64(self, buf: &mut [u8], n: u64) {
165 let bytes = if self.is_big_endian() {
166 n.to_be_bytes()
167 } else {
168 n.to_le_bytes()
169 };
170 buf[..8].copy_from_slice(&bytes);
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
176pub enum RunTimeEndian {
177 Little,
179 Big,
181}
182
183impl Default for RunTimeEndian {
184 #[cfg(target_endian = "little")]
185 #[inline]
186 fn default() -> RunTimeEndian {
187 RunTimeEndian::Little
188 }
189
190 #[cfg(target_endian = "big")]
191 #[inline]
192 fn default() -> RunTimeEndian {
193 RunTimeEndian::Big
194 }
195}
196
197impl Endianity for RunTimeEndian {
198 #[inline]
199 fn is_big_endian(self) -> bool {
200 self != RunTimeEndian::Little
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
206pub struct LittleEndian;
207
208impl Default for LittleEndian {
209 #[inline]
210 fn default() -> LittleEndian {
211 LittleEndian
212 }
213}
214
215impl Endianity for LittleEndian {
216 #[inline]
217 fn is_big_endian(self) -> bool {
218 false
219 }
220}
221
222#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
224pub struct BigEndian;
225
226impl Default for BigEndian {
227 #[inline]
228 fn default() -> BigEndian {
229 BigEndian
230 }
231}
232
233impl Endianity for BigEndian {
234 #[inline]
235 fn is_big_endian(self) -> bool {
236 true
237 }
238}
239
240#[cfg(target_endian = "little")]
242pub type NativeEndian = LittleEndian;
243
244#[cfg(target_endian = "little")]
245#[allow(non_upper_case_globals)]
246#[doc(hidden)]
247pub const NativeEndian: LittleEndian = LittleEndian;
248
249#[cfg(target_endian = "big")]
251pub type NativeEndian = BigEndian;
252
253#[cfg(target_endian = "big")]
254#[allow(non_upper_case_globals)]
255#[doc(hidden)]
256pub const NativeEndian: BigEndian = BigEndian;