endian/
lib.rs

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}