1#![no_std]
2
3use core::ops::{BitAnd, BitOr, BitXor};
4use core::{mem, slice};
5
6pub trait Endian<T> {}
8
9macro_rules! impl_Endian{
10 ( for $e:ident) => {
11 impl<T> BitAnd for $e<T>
12 where
13 T: BitAnd,
14 {
15 type Output = $e<<T as BitAnd>::Output>;
16
17 #[inline]
18 fn bitand(self, other: Self) -> Self::Output {
19 $e(self.0 & other.0)
20 }
21 }
22
23 impl<T> BitOr for $e<T>
24 where
25 T: BitOr,
26 {
27 type Output = $e<<T as BitOr>::Output>;
28
29 #[inline]
30 fn bitor(self, other: Self) -> Self::Output {
31 $e(self.0 | other.0)
32 }
33 }
34
35 impl<T> BitXor for $e<T>
36 where
37 T: BitXor,
38 {
39 type Output = $e<<T as BitXor>::Output>;
40
41 #[inline]
42 fn bitxor(self, other: Self) -> Self::Output {
43 $e(self.0 ^ other.0)
44 }
45 }
46
47 impl<T> $e<T>
48 where
49 T: Sized + Copy,
50 {
51 #[inline]
52 pub const unsafe fn from_byte_slice(bytes: &[u8]) -> $e<T> {
53 debug_assert!(bytes.len() >= mem::size_of::<T>());
54 $e({ *(bytes.as_ptr() as *const T) })
55 }
56
57 #[inline]
58 pub fn as_byte_slice(&self) -> &[u8] {
59 unsafe { slice::from_raw_parts(&self.0 as *const T as *const u8, mem::size_of::<T>()) }
60 }
61
62 #[inline]
63 pub fn as_byte_slice_mut(&mut self) -> &mut [u8] {
64 unsafe { slice::from_raw_parts_mut(&mut self.0 as *mut T as *mut u8, mem::size_of::<T>()) }
65 }
66 }
67 }
68}
69
70#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
74#[repr(transparent)]
75pub struct BigEndian<T>(T);
76
77impl<T> Endian<T> for BigEndian<T> {}
78
79macro_rules! impl_for_BigEndian {
80 ( $t:ident ) => {
81 impl From<BigEndian<$t>> for $t {
82 #[inline]
83 fn from(data: BigEndian<$t>) -> $t {
84 $t::from_be(data.0)
85 }
86 }
87
88 impl From<$t> for BigEndian<$t> {
89 #[inline]
90 fn from(data: $t) -> Self {
91 BigEndian(data.to_be())
92 }
93 }
94
95 impl From<LittleEndian<$t>> for BigEndian<$t> {
96 #[inline]
97 fn from(data: LittleEndian<$t>) -> Self {
98 BigEndian(data.0.swap_bytes())
99 }
100 }
101
102 impl BigEndian<$t>{
104 #[inline]
107 pub const fn to_bytes(self) -> [u8; mem::size_of::<BigEndian<$t>>()] {
108 unsafe { mem::transmute(self) }
109 }
110
111 #[inline]
114 pub const fn from_bytes(bytes: [u8; mem::size_of::<BigEndian<$t>>()]) -> BigEndian<$t> {
115 unsafe { mem::transmute(bytes) }
116 }
117 }
118 };
119}
120
121impl_Endian!(for BigEndian);
122impl_for_BigEndian!(u16);
123impl_for_BigEndian!(u32);
124impl_for_BigEndian!(u64);
125impl_for_BigEndian!(u128);
126impl_for_BigEndian!(usize);
127impl_for_BigEndian!(i16);
128impl_for_BigEndian!(i32);
129impl_for_BigEndian!(i64);
130impl_for_BigEndian!(i128);
131impl_for_BigEndian!(isize);
132
133#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
137#[repr(transparent)]
138pub struct LittleEndian<T>(T);
139
140impl<T> Endian<T> for LittleEndian<T> {}
141
142macro_rules! impl_for_LittleEndian {
143 ( $t:ident ) => {
144 impl From<LittleEndian<$t>> for $t {
145 #[inline]
146 fn from(data: LittleEndian<$t>) -> $t {
147 $t::from_le(data.0)
148 }
149 }
150
151 impl From<$t> for LittleEndian<$t> {
152 #[inline]
153 fn from(data: $t) -> Self {
154 LittleEndian(data.to_le())
155 }
156 }
157
158 impl From<BigEndian<$t>> for LittleEndian<$t> {
159 #[inline]
160 fn from(data: BigEndian<$t>) -> Self {
161 LittleEndian(data.0.swap_bytes())
162 }
163 }
164
165 impl LittleEndian<$t>{
166 #[inline]
169 pub const fn to_bytes(self) -> [u8; mem::size_of::<LittleEndian<$t>>()] {
170 unsafe { mem::transmute(self) }
171 }
172
173 #[inline]
176 pub const fn from_bytes(bytes: [u8; mem::size_of::<LittleEndian<$t>>()]) -> LittleEndian<$t> {
177 unsafe { mem::transmute(bytes) }
178 }
179 }
180 };
181}
182
183impl_Endian!(for LittleEndian);
184impl_for_LittleEndian!(u16);
185impl_for_LittleEndian!(u32);
186impl_for_LittleEndian!(u64);
187impl_for_LittleEndian!(u128);
188impl_for_LittleEndian!(usize);
189impl_for_LittleEndian!(i16);
190impl_for_LittleEndian!(i32);
191impl_for_LittleEndian!(i64);
192impl_for_LittleEndian!(i128);
193impl_for_LittleEndian!(isize);
194
195pub type NetworkOrder<T> = BigEndian<T>;
197
198pub mod types {
200 #![allow(non_camel_case_types)]
201
202 use super::*;
203
204 pub type i16_be = BigEndian<i16>;
205 pub type i32_be = BigEndian<i32>;
206 pub type i64_be = BigEndian<i64>;
207 pub type i128_be = BigEndian<i128>;
208 pub type isize_be = BigEndian<isize>;
209
210 pub type u16_be = BigEndian<u16>;
211 pub type u32_be = BigEndian<u32>;
212 pub type u64_be = BigEndian<u64>;
213 pub type u128_be = BigEndian<u128>;
214 pub type usize_be = BigEndian<usize>;
215
216 pub type i16_le = LittleEndian<i16>;
217 pub type i32_le = LittleEndian<i32>;
218 pub type i64_le = LittleEndian<i64>;
219 pub type i128_le = LittleEndian<i128>;
220 pub type isize_le = LittleEndian<isize>;
221
222 pub type u16_le = LittleEndian<u16>;
223 pub type u32_le = LittleEndian<u32>;
224 pub type u64_le = LittleEndian<u64>;
225 pub type u128_le = LittleEndian<u128>;
226 pub type usize_le = LittleEndian<usize>;
227
228 pub type i16_net = NetworkOrder<i16>;
229 pub type i32_net = NetworkOrder<i32>;
230 pub type i128_net = NetworkOrder<i128>;
231 pub type isize_net = NetworkOrder<isize>;
232
233 pub type u16_net = NetworkOrder<u16>;
234 pub type u32_net = NetworkOrder<u32>;
235 pub type u64_net = NetworkOrder<u64>;
236 pub type u128_net = NetworkOrder<u128>;
237 pub type usize_net = NetworkOrder<usize>;
238}
239
240#[cfg(test)]
241mod tests{
242 use super::*;
243 use super::types::*;
244
245 #[test]
246 fn from_to_bytes(){
247 macro_rules! test{
248 ($e:ident for $t:ident in $r:expr) => {
249 for i in $r{
250 let j = $e::<$t>::from(i);
251 assert_eq!($e::<$t>::from_bytes(j.to_bytes()) , j);
252 }
253 }
254 }
255
256 test!(BigEndian for i16 in -10000..10000);
257 test!(BigEndian for i32 in -10000..10000);
258 test!(BigEndian for i64 in -10000..10000);
259 test!(BigEndian for i128 in -10000..10000);
260
261 test!(LittleEndian for i16 in -10000..10000);
262 test!(LittleEndian for i32 in -10000..10000);
263 test!(LittleEndian for i64 in -10000..10000);
264 test!(LittleEndian for i128 in -10000..10000);
265
266 test!(BigEndian for u16 in 0..20000);
267 test!(BigEndian for u32 in 0..20000);
268 test!(BigEndian for u64 in 0..20000);
269 test!(BigEndian for u128 in 0..20000);
270
271 test!(LittleEndian for u16 in 0..20000);
272 test!(LittleEndian for u32 in 0..20000);
273 test!(LittleEndian for u64 in 0..20000);
274 test!(LittleEndian for u128 in 0..20000);
275 }
276
277 #[test]
278 fn to_bytes_std(){
279 macro_rules! test{
280 ( for $t:ident in $r:expr) => {
281 for i in $r{
282 assert_eq!( BigEndian::<$t>::from(i).to_bytes() , i.to_be_bytes());
283 assert_eq!(LittleEndian::<$t>::from(i).to_bytes() , i.to_le_bytes());
284 }
285 }
286 }
287
288 test!(for i16 in -10000..10000);
289 test!(for i32 in -10000..10000);
290 test!(for i64 in -10000..10000);
291 test!(for i128 in -10000..10000);
292
293 test!(for i16 in 0..20000);
294 test!(for i32 in 0..20000);
295 test!(for i64 in 0..20000);
296 test!(for i128 in 0..20000);
297 }
298
299 #[test]
300 fn as_to_byte_slice(){
301 macro_rules! test{
302 ($e:ident for $t:ident in $r:expr) => {
303 for i in $r{
304 let mut j = $e::<$t>::from(i);
305 assert_eq!(unsafe{$e::<$t>::from_byte_slice(j.as_byte_slice())} , j);
306 assert_eq!(unsafe{$e::<$t>::from_byte_slice(j.as_byte_slice_mut())} , j);
307 }
308 }
309 }
310
311 test!(BigEndian for i16 in -10000..10000);
312 test!(BigEndian for i32 in -10000..10000);
313 test!(BigEndian for i64 in -10000..10000);
314 test!(BigEndian for i128 in -10000..10000);
315
316 test!(LittleEndian for i16 in -10000..10000);
317 test!(LittleEndian for i32 in -10000..10000);
318 test!(LittleEndian for i64 in -10000..10000);
319 test!(LittleEndian for i128 in -10000..10000);
320
321 test!(BigEndian for u16 in 0..20000);
322 test!(BigEndian for u32 in 0..20000);
323 test!(BigEndian for u64 in 0..20000);
324 test!(BigEndian for u128 in 0..20000);
325
326 test!(LittleEndian for u16 in 0..20000);
327 test!(LittleEndian for u32 in 0..20000);
328 test!(LittleEndian for u64 in 0..20000);
329 test!(LittleEndian for u128 in 0..20000);
330 }
331
332}
333
334#[cfg(doctest)]
335mod test_readme {
336 macro_rules! external_doc_test {
337 ($x:expr) => {
338 #[doc = $x]
339 extern {}
340 };
341 }
342 external_doc_test!(include_str!("../README.md"));
343}