1#![no_std]
2
3use core::{cmp::Ordering, convert::From, hash::{Hash, Hasher}, marker::PhantomData, mem};
4
5use num_traits::{NumAssign, cast::AsPrimitive, int::PrimInt};
6
7pub trait Endian: private::Sealed {
8 const is_big: bool = !Self::is_lil;
9 const is_lil: bool = !Self::is_big;
10
11 fn read<N: 'static + PrimInt + NumAssign + ShlAssign<usize>>(bs: &[u8]) -> N where u8: AsPrimitive<N>;
12 fn write<N: PrimInt + NumAssign + ShrAssign<usize>>(bs: &mut [u8], n: N) where N: AsPrimitive<u8>;
13
14 #[inline]
15 fn from<N: PrimInt + NumAssign + ShrAssign<usize>>(ns: &[N], bs: &mut [u8]) where N: AsPrimitive<u8> {
16 assert_eq!(bs.len(), mem::size_of::<N>() * ns.len());
17 for (np, bs) in Iterator::zip(ns.iter(), bs.chunks_mut(mem::size_of::<N>())) {
18 Self::write(bs, *np);
19 }
20 }
21
22 #[inline]
23 fn to<N: 'static + PrimInt + NumAssign + ShlAssign<usize>>(bs: &[u8], ns: &mut [N]) where u8: AsPrimitive<N> {
24 assert_eq!(bs.len(), mem::size_of::<N>() * ns.len());
25 for (bs, np) in Iterator::zip(bs.chunks(mem::size_of::<N>()), ns.iter_mut()) {
26 *np = Self::read(bs);
27 }
28 }
29
30 #[inline] #[deprecated]
31 fn read_u(bs: &[u8]) -> u64 { Self::read(bs) }
32 #[inline] #[deprecated]
33 fn read_i(bs: &[u8]) -> u64 { Self::read(bs) }
34 #[inline] #[deprecated]
35 fn write_u(bs: &mut [u8], n: u64) { Self::write(bs, n) }
36 #[inline] #[deprecated]
37 fn write_i(bs: &mut [u8], n: i64) { Self::write(bs, n) }
38 #[inline] #[deprecated]
39 fn to_u16s(bs: &[u8], ns: &mut [u16]) { Self::to(bs, ns) }
40 #[inline] #[deprecated]
41 fn to_i16s(bs: &[u8], ns: &mut [i16]) { Self::to(bs, ns) }
42 #[inline] #[deprecated]
43 fn from_u16s(ns: &[u16], bs: &mut [u8]) { Self::from(ns, bs) }
44 #[inline] #[deprecated]
45 fn from_i16s(ns: &[i16], bs: &mut [u8]) { Self::from(ns, bs) }
46 #[inline] #[deprecated]
47 fn to_u32s(bs: &[u8], ns: &mut [u32]) { Self::to(bs, ns) }
48 #[inline] #[deprecated]
49 fn to_i32s(bs: &[u8], ns: &mut [i32]) { Self::to(bs, ns) }
50 #[inline] #[deprecated]
51 fn from_u32s(ns: &[u32], bs: &mut [u8]) { Self::from(ns, bs) }
52 #[inline] #[deprecated]
53 fn from_i32s(ns: &[i32], bs: &mut [u8]) { Self::from(ns, bs) }
54 #[inline] #[deprecated]
55 fn to_u64s(bs: &[u8], ns: &mut [u64]) { Self::to(bs, ns) }
56 #[inline] #[deprecated]
57 fn to_i64s(bs: &[u8], ns: &mut [i64]) { Self::to(bs, ns) }
58 #[inline] #[deprecated]
59 fn from_u64s(ns: &[u64], bs: &mut [u8]) { Self::from(ns, bs) }
60 #[inline] #[deprecated]
61 fn from_i64s(ns: &[i64], bs: &mut [u8]) { Self::from(ns, bs) }
62}
63
64mod private {
65 pub trait Sealed {}
66}
67
68#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
69pub struct Big;
70
71#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
72pub struct Lil;
73
74impl private::Sealed for Big {}
75impl private::Sealed for Lil {}
76
77impl Endian for Big {
78 const is_big: bool = true;
79
80 #[inline]
81 fn read<N: 'static + PrimInt + NumAssign + ShlAssign<usize>>(bs: &[u8]) -> N where u8: AsPrimitive<N> {
82 assert!(mem::size_of::<N>() >= bs.len());
83 let mut n = 0.as_();
84 for &b in bs {
85 n <<= 8;
86 n += b.as_();
87 }
88 n
89 }
90
91 #[inline]
92 fn write<N: PrimInt + NumAssign + ShrAssign<usize>>(bs: &mut [u8], mut n: N) where N: AsPrimitive<u8> {
93 assert!(mem::size_of::<N>() >= bs.len());
94 for bp in bs.iter_mut().rev() {
95 *bp = n.as_();
96 n >>= 8;
97 }
98 }
99}
100
101impl Endian for Lil {
102 const is_lil: bool = true;
103
104 #[inline]
105 fn read<N: 'static + PrimInt + NumAssign + ShlAssign<usize>>(bs: &[u8]) -> N where u8: AsPrimitive<N> {
106 assert!(mem::size_of::<N>() >= bs.len());
107 let mut n = 0.as_();
108 for &b in bs.iter().rev() {
109 n <<= 8;
110 n += b.as_();
111 }
112 n
113 }
114
115 #[inline]
116 fn write<N: PrimInt + NumAssign + ShrAssign<usize>>(bs: &mut [u8], mut n: N) where N: AsPrimitive<u8> {
117 assert!(mem::size_of::<N>() >= bs.len());
118 for bp in bs {
119 *bp = n.as_();
120 n >>= 8;
121 }
122 }
123}
124
125#[derive(Clone, Copy)]
126#[repr(transparent)]
127pub struct End<A, E: Endian>(A, PhantomData<E>);
128
129impl<A: PartialEq, E: Endian> PartialEq for End<A, E> {
130 #[inline]
131 fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
132}
133impl<A: Eq, E: Endian> Eq for End<A, E> {}
134impl<A: Hash, E: Endian> Hash for End<A, E> {
135 #[inline]
136 fn hash<H: Hasher>(&self, h: &mut H) { self.0.hash(h) }
137}
138
139macro_rules! impl_fmt {
140 ($c:path) => {
141 impl<A: Copy, E: Copy + Endian> $c for End<A, E> where A: From<End<A, E>> + $c {
142 #[inline]
143 fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
144 <A>::from(*self).fmt(fmt)
145 }
146 }
147 };
148
149 ($c:path, $($cs:path),*) => { impl_fmt!($c); $(impl_fmt!($cs);)* }
150}
151
152use core::fmt;
153impl_fmt!(fmt::Debug, fmt::Display, fmt::Octal, fmt::LowerHex, fmt::UpperHex);
154
155macro_rules! do_impls {
156 ($t:ty) => {
157 impl<E: Endian> From<$t> for End<$t, E> {
158 #[inline]
159 fn from(a: $t) -> Self {
160 End(if cfg!(target_endian = "little") == E::is_lil { a } else { a.swap_bytes() },
161 PhantomData)
162 }
163 }
164
165 impl<E: Endian> From<End<$t, E>> for $t {
166 #[inline]
167 fn from(End(a, _): End<$t, E>) -> Self {
168 if cfg!(target_endian = "little") == E::is_lil { a } else { a.swap_bytes() }
169 }
170 }
171 };
172
173 ($t:ty, $($ts:ty),*) => { do_impls!($t); $(do_impls!($ts);)* }
174}
175
176do_impls!(usize, u8, u16, u32, u64, u128,
177 isize, i8, i16, i32, i64, i128);
178
179macro_rules! impl_op {
180 ($op:ident, $f:ident) => {
181 impl<A: $op<B>, B, E: Endian> $op<B> for End<A, E>
182 where A: From<End<A, E>>, End<<A as $op<B>>::Output, E>: From<<A as $op<B>>::Output> {
183 type Output = End<<A as $op<B>>::Output, E>;
184 #[inline]
185 fn $f(self, other: B) -> Self::Output { A::$f(self.into(), other).into() }
186 }
187 }
188}
189
190macro_rules! impl_op_assign {
191 ($op:ident, $f:ident) => {
192 impl<A: $op<B>, B, E: Endian> $op<B> for End<A, E> {
193 #[inline]
194 fn $f(&mut self, operand: B) { A::$f(&mut self.0, operand) }
195 }
196 }
197}
198
199macro_rules! impl_op_unary {
200 ($op:ident, $f:ident) => {
201 impl<A: $op, E: Endian> $op for End<A, E>
202 where A: From<End<A, E>>, End<<A as $op>::Output, E>: From<<A as $op>::Output> {
203 type Output = End<<A as $op>::Output, E>;
204 #[inline]
205 fn $f(self) -> Self::Output { A::$f(self.into()).into() }
206 }
207 }
208}
209
210use core::ops::*;
211
212impl_op!(BitAnd, bitand);
213impl_op!(BitOr, bitor);
214impl_op!(BitXor, bitxor);
215impl_op!(Add, add);
216impl_op!(Sub, sub);
217impl_op!(Mul, mul);
218impl_op!(Div, div);
219impl_op!(Rem, rem);
220impl_op!(Shl, shl);
221impl_op!(Shr, shr);
222
223impl_op_unary!(Neg, neg);
224impl_op_unary!(Not, not);
225
226impl_op_assign!(BitAndAssign, bitand_assign);
227impl_op_assign!(BitOrAssign, bitor_assign);
228impl_op_assign!(BitXorAssign, bitxor_assign);
229
230impl<A: Copy + PartialOrd, E: Copy + Endian> PartialOrd for End<A, E> where Self: Into<A> {
231 #[inline]
232 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
233 A::partial_cmp(&(*self).into(), &(*other).into())
234 }
235}
236
237impl<A: Copy + Ord, E: Copy + Endian> Ord for End<A, E> where Self: Into<A> {
238 #[inline]
239 fn cmp(&self, other: &Self) -> Ordering {
240 A::cmp(&(*self).into(), &(*other).into())
241 }
242}