1use std::fmt::{Debug, Display, Formatter, Error};
2
3pub trait EndianBufFor<Out> {
4 #[inline(always)]
5 fn reverse(&mut self);
6 #[inline(always)]
7 fn native(self) -> Out;
8}
9
10pub trait FromBuf: Sized + Clone {
11 type Buf: EndianBufFor<Self>;
12
13 #[inline(always)]
14 fn from_buf(buf: Self::Buf) -> Self {
15 buf.native()
16 }
17
18 #[inline(always)]
19 fn into_buf(self) -> Self::Buf;
20}
21
22pub trait IntoNativeEndian {
23 type Out;
24
25 #[inline(always)]
26 fn native(self) -> Self::Out;
27}
28
29#[derive(Clone)]
30pub struct Big<T: FromBuf>(pub T::Buf);
31#[derive(Clone)]
32pub struct Little<T: FromBuf>(pub T::Buf);
33
34impl<T: FromBuf + Debug> Debug for Big<T>
35 where Self: Clone
36{
37 #[inline(always)]
38 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
39 write!(f, "Big({:?})", self.clone().native())
40 }
41}
42
43impl<T: FromBuf + Debug> Debug for Little<T>
44 where Self: Clone
45{
46 #[inline(always)]
47 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
48 write!(f, "Big({:?})", self.clone().native())
49 }
50}
51
52impl<T: FromBuf + Display> Display for Big<T>
53 where Self: Clone
54{
55 #[inline(always)]
56 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
57 self.clone().native().fmt(f)
58 }
59}
60
61impl<T: FromBuf + Debug> Display for Little<T>
62 where Self: Clone
63{
64 #[inline(always)]
65 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
66 self.clone().native().fmt(f)
67 }
68}
69
70macro_rules! impl_buf_traits {
71 ($type:ty, $count:expr) => {
72 impl EndianBufFor<$type> for [u8; $count] {
73 #[inline(always)]
74 fn reverse(&mut self) {
75 self.as_mut().reverse()
76 }
77
78 #[inline(always)]
79 fn native(self) -> $type {
80 unsafe { ::std::mem::transmute(self) }
81 }
82 }
83
84 impl FromBuf for $type {
85 type Buf = [u8; $count];
86
87 #[inline(always)]
88 fn into_buf(self) -> Self::Buf {
89 unsafe { ::std::mem::transmute(self) }
90 }
91 }
92
93 impl Copy for Big<$type> {}
94 impl Copy for Little<$type> {}
95 };
96}
97
98impl_buf_traits!(u8, 1);
99impl_buf_traits!(u16, 2);
100impl_buf_traits!(u32, 4);
101impl_buf_traits!(u64, 8);
102
103impl_buf_traits!(i8, 1);
104impl_buf_traits!(i16, 2);
105impl_buf_traits!(i32, 4);
106impl_buf_traits!(i64, 8);
107
108impl_buf_traits!(f32, 4);
109impl_buf_traits!(f64, 8);
110
111#[cfg(target_endian = "big")]
112mod trait_impls {
113 use super::{FromBuf, EndianBufFor, IntoNativeEndian, Big, Little};
114
115 impl<T: FromBuf> Big<T> {
116 #[inline(always)]
117 fn new(inner: T) -> Self {
118 Big(inner.into_buf())
119 }
120 }
121
122 impl<T: FromBuf> Little<T> {
123 #[inline(always)]
124 fn new(inner: T) -> Self {
125 let mut buf = inner.into_buf();
126 buf.reverse();
127 Little(buf)
128 }
129 }
130
131 impl<T: FromBuf> IntoNativeEndian for Big<T> {
132 type Out = T;
133
134 #[inline(always)]
135 fn native(self) -> Self::Out {
136 T::from_buf(self.0)
137 }
138 }
139
140 impl<T: FromBuf> IntoNativeEndian for Little<T> {
141 type Out = T;
142
143 #[inline(always)]
144 fn native(mut self) -> Self::Out {
145 self.0.reverse();
146 T::from_buf(self.0)
147 }
148 }
149}
150
151#[cfg(target_endian = "little")]
152mod trait_impls {
153 use super::{FromBuf, EndianBufFor, IntoNativeEndian, Big, Little};
154
155 impl<T: FromBuf> Big<T> {
156 #[inline(always)]
157 pub fn new(inner: T) -> Self {
158 let mut buf = inner.into_buf();
159 buf.reverse();
160 Big(buf)
161 }
162 }
163
164 impl<T: FromBuf> Little<T> {
165 #[inline(always)]
166 pub fn new(inner: T) -> Self {
167 Little(inner.into_buf())
168 }
169 }
170
171 impl<T: FromBuf> IntoNativeEndian for Big<T> {
172 type Out = T;
173
174 #[inline(always)]
175 fn native(mut self) -> Self::Out {
176 self.0.reverse();
177 T::from_buf(self.0)
178 }
179 }
180
181 impl<T: FromBuf> IntoNativeEndian for Little<T> {
182 type Out = T;
183
184 #[inline(always)]
185 fn native(self) -> Self::Out {
186 T::from_buf(self.0)
187 }
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 #[test]
194 fn it_works() {}
195}