1use crate::AllBytesValid;
2use std::cmp::Ordering;
3use std::fmt;
4use std::mem;
5use std::slice;
6
7#[repr(C, packed)]
14pub struct Le<T>(T);
15
16impl<T> Le<T>
17where
18 T: Endian,
19{
20 pub fn new(t: T) -> Le<T> {
23 Le(t.into_le())
24 }
25
26 pub fn get(&self) -> T {
32 self.0.from_le()
33 }
34
35 pub fn set(&mut self, val: T) {
41 self.0 = val.into_le();
42 }
43
44 pub(crate) fn from_slice(bytes: &[u8]) -> &[Le<T>] {
45 unsafe {
55 assert_eq!(mem::align_of::<Le<T>>(), 1);
56 assert!(bytes.len() % mem::size_of::<Le<T>>() == 0);
57 fn all_bytes_valid<T: AllBytesValid>() {}
58 all_bytes_valid::<Le<T>>();
59
60 slice::from_raw_parts(
61 bytes.as_ptr().cast::<Le<T>>(),
62 bytes.len() / mem::size_of::<Le<T>>(),
63 )
64 }
65 }
66
67 pub(crate) fn from_slice_mut(bytes: &mut [u8]) -> &mut [Le<T>] {
68 unsafe {
73 assert_eq!(mem::align_of::<Le<T>>(), 1);
74 assert!(bytes.len() % mem::size_of::<Le<T>>() == 0);
75 slice::from_raw_parts_mut(
76 bytes.as_mut_ptr().cast::<Le<T>>(),
77 bytes.len() / mem::size_of::<Le<T>>(),
78 )
79 }
80 }
81}
82
83impl<T: Copy> Clone for Le<T> {
84 fn clone(&self) -> Self {
85 *self
86 }
87}
88
89impl<T: Copy> Copy for Le<T> {}
90
91impl<T: Endian + PartialEq> PartialEq for Le<T> {
92 fn eq(&self, other: &Le<T>) -> bool {
93 self.get() == other.get()
94 }
95}
96
97impl<T: Endian + PartialEq> PartialEq<T> for Le<T> {
98 fn eq(&self, other: &T) -> bool {
99 self.get() == *other
100 }
101}
102
103impl<T: Endian + Eq> Eq for Le<T> {}
104
105impl<T: Endian + PartialOrd> PartialOrd for Le<T> {
106 fn partial_cmp(&self, other: &Le<T>) -> Option<Ordering> {
107 self.get().partial_cmp(&other.get())
108 }
109}
110
111impl<T: Endian + Ord> Ord for Le<T> {
112 fn cmp(&self, other: &Le<T>) -> Ordering {
113 self.get().cmp(&other.get())
114 }
115}
116
117impl<T: Endian + fmt::Debug> fmt::Debug for Le<T> {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 self.get().fmt(f)
120 }
121}
122
123impl<T: Endian> From<T> for Le<T> {
124 fn from(t: T) -> Le<T> {
125 Le::new(t)
126 }
127}
128
129unsafe impl<T: AllBytesValid> AllBytesValid for Le<T> {}
130
131pub trait Endian: AllBytesValid + Copy + Sized {
133 fn into_le(self) -> Self;
136 #[allow(clippy::wrong_self_convention)]
139 fn from_le(self) -> Self;
140}
141
142macro_rules! primitives {
143 ($($t:ident)*) => ($(
144 impl Endian for $t {
145 #[inline]
146 fn into_le(self) -> Self {
147 Self::from_ne_bytes(self.to_le_bytes())
148 }
149
150 #[inline]
151 fn from_le(self) -> Self {
152 Self::from_le_bytes(self.to_ne_bytes())
153 }
154 }
155 )*)
156}
157
158primitives! {
159 u8 i8
160 u16 i16
161 u32 i32
162 u64 i64
163 f32 f64
164}
165
166#[allow(clippy::unused_unit)]
167macro_rules! tuples {
168 ($(($($t:ident)*))*) => ($(
169 #[allow(non_snake_case)]
170 impl <$($t:Endian,)*> Endian for ($($t,)*) {
171 #[allow(clippy::unused_unit)]
172 fn into_le(self) -> Self {
173 let ($($t,)*) = self;
174 ($($t.into_le(),)*)
176 }
177
178 #[allow(clippy::unused_unit)]
179 fn from_le(self) -> Self {
180 let ($($t,)*) = self;
181 ($($t.from_le(),)*)
183 }
184 }
185 )*)
186}
187
188tuples! {
189 ()
190 (T1)
191 (T1 T2)
192 (T1 T2 T3)
193 (T1 T2 T3 T4)
194 (T1 T2 T3 T4 T5)
195 (T1 T2 T3 T4 T5 T6)
196 (T1 T2 T3 T4 T5 T6 T7)
197 (T1 T2 T3 T4 T5 T6 T7 T8)
198 (T1 T2 T3 T4 T5 T6 T7 T8 T9)
199 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
200}