1pub trait VecByteConversion
3where
4 Self: Sized,
5{
6 fn to_le_bytes(&self) -> Vec<u8>;
7 fn from_le_bytes(bytes: &[u8]) -> Option<Self>;
8 fn to_be_bytes(&self) -> Vec<u8>;
9 fn from_be_bytes(bytes: &[u8]) -> Option<Self>;
10 fn to_ne_bytes(&self) -> Vec<u8>;
11 fn from_ne_bytes(bytes: &[u8]) -> Option<Self>;
12}
13
14pub trait ByteConversion<const N: usize> {
16 fn to_le_bytes_(self) -> [u8; N];
17 fn from_le_bytes_(bytes: [u8; N]) -> Self;
18 fn to_be_bytes_(self) -> [u8; N];
19 fn from_be_bytes_(bytes: [u8; N]) -> Self;
20 fn to_ne_bytes_(self) -> [u8; N];
21 fn from_ne_bytes_(bytes: [u8; N]) -> Self;
22}
23
24macro_rules! impl_byte_conversion {
25 ($x:ty) => (
26 impl ByteConversion<{ size_of::<$x>() }> for $x {
27 fn to_le_bytes_(self) -> [u8; size_of::<$x>()] {
28 <$x>::to_le_bytes(self)
29 }
30
31 fn from_le_bytes_(bytes: [u8; size_of::<$x>()]) -> Self {
32 <$x>::from_le_bytes(bytes)
33 }
34
35 fn to_be_bytes_(self) -> [u8; size_of::<$x>()] {
36 <$x>::to_be_bytes(self)
37 }
38
39 fn from_be_bytes_(bytes: [u8; size_of::<$x>()]) -> Self {
40 <$x>::from_be_bytes(bytes)
41 }
42
43 fn to_ne_bytes_(self) -> [u8; size_of::<$x>()] {
44 <$x>::to_ne_bytes(self)
45 }
46
47 fn from_ne_bytes_(bytes: [u8; size_of::<$x>()]) -> Self {
48 <$x>::from_ne_bytes(bytes)
49 }
50 }
51 impl VecByteConversion for Vec<$x> {
52 fn to_le_bytes(&self) -> Vec<u8> {
53 self.iter().flat_map(|v| v.to_le_bytes()).collect()
54 }
55
56 fn from_le_bytes(bytes: &[u8]) -> Option<Self> {
57 if bytes.len().is_multiple_of(size_of::<$x>()) {
58 Some(
59 bytes
60 .chunks_exact(size_of::<$x>())
61 .map(|v| {
62 <$x>::from_le_bytes(unsafe {
63 (v.as_ptr() as *const [u8; size_of::<$x>()]).read()
64 })
65 })
66 .collect(),
67 )
68 } else {
69 None
70 }
71 }
72 fn to_be_bytes(&self) -> Vec<u8> {
73 self.iter().flat_map(|v| v.to_be_bytes()).collect()
74 }
75
76 fn from_be_bytes(bytes: &[u8]) -> Option<Self> {
77 if bytes.len().is_multiple_of(size_of::<$x>()) {
78 Some(
79 bytes
80 .chunks_exact(size_of::<$x>())
81 .map(|v| {
82 <$x>::from_be_bytes(unsafe {
83 (v.as_ptr() as *const [u8; size_of::<$x>()]).read()
84 })
85 })
86 .collect(),
87 )
88 } else {
89 None
90 }
91 }
92 fn to_ne_bytes(&self) -> Vec<u8> {
93 self.iter().flat_map(|v| v.to_ne_bytes()).collect()
94 }
95
96 fn from_ne_bytes(bytes: &[u8]) -> Option<Self> {
97 if bytes.len().is_multiple_of(size_of::<$x>()) {
98 Some(
99 bytes
100 .chunks_exact(size_of::<$x>())
101 .map(|v| {
102 <$x>::from_ne_bytes(unsafe {
103 (v.as_ptr() as *const [u8; size_of::<$x>()]).read()
104 })
105 })
106 .collect(),
107 )
108 } else {
109 None
110 }
111 }
112 }
113 );
114 ($x:ty, $($y:ty),+) => (
115 impl_byte_conversion!($x);
116 impl_byte_conversion!($($y),+);
117 )
118}
119
120impl_byte_conversion!(
121 usize, isize, i8, u8, i16, i32, i64, i128, u16, u32, u64, u128, f32, f64
122);
123
124pub trait LossyCast<T> {
126 fn _as(self) -> T;
127 fn _from(v: T) -> Self;
128}
129
130macro_rules! impl_cast {
131 ($x:ty, $y:ty) => (
132 impl LossyCast<$y> for $x {
133 fn _as(self) -> $y {
134 self as _
135 }
136 fn _from(v: $y) -> $x {
137 v as _
138 }
139 }
140 );
141 ($x:ty,$y:ty, $($z:ty),+) => (
142 impl_cast!($x, $y);
143 impl_cast!($x, $($z),+);
144 )
145}
146
147impl_cast!(
148 usize, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
149);
150impl_cast!(
151 isize, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
152);
153impl_cast!(
154 i8, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
155);
156impl_cast!(
157 u8, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
158);
159impl_cast!(
160 i16, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
161);
162impl_cast!(
163 i32, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
164);
165impl_cast!(
166 i64, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
167);
168impl_cast!(
169 u16, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
170);
171impl_cast!(
172 u32, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
173);
174impl_cast!(
175 u64, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
176);
177impl_cast!(
178 f32, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
179);
180impl_cast!(
181 f64, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
182);
183impl_cast!(
184 i128, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
185);
186impl_cast!(
187 u128, usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
188);
189
190#[cfg(test)]
191mod tests {
192 use crate::VecByteConversion;
193
194 macro_rules! impl_vec_test {
195 ($x:ty) => (
196 let src_vec = vec![<$x>::MAX/(4 as $x), <$x>::MAX/(2 as $x),<$x>::MAX/(4 as $x)*(3 as $x),<$x>::MAX];
197 let round_trip_vec = Vec::<$x>::from_le_bytes(&src_vec.to_le_bytes()).unwrap();
198 for idx in 0..4 {
199 assert_eq!(
200 src_vec[idx],
201 Vec::<$x>::from_le_bytes(&src_vec.to_le_bytes()).unwrap()[idx]
202 );
203 }
204 );
205 ($x:ty, $($y:ty),+) => (
206 impl_vec_test!($x);
207 impl_vec_test!($($y),+);
208 )
209 }
210
211 #[test]
212 fn test_roundtrip() {
213 impl_vec_test!(
214 usize, isize, i8, u8, i16, i32, i64, u16, u32, u64, i128, u128, f32, f64
215 );
216 }
217}