1use core::num::Wrapping;
2
3/// An `Encoding` of a type `T` can be converted to/from its byte
4/// representation without any byte swapping or other computation.
5///
6/// The `Self: Copy` constraint addresses `clippy::declare_interior_mutable_const`.
7pub trait Encoding<T>: From<T> + Into<T>
8where
9 Self: Copy,
10{
11 const ZERO: Self;
12}
13
14macro_rules! define_endian {
15 ($endian:ident) => {
16 #[derive(Clone, Copy)]
17 #[repr(transparent)]
18 pub struct $endian<T>(T);
19 };
20}
21
22macro_rules! impl_endian {
23 ($endian:ident, $base:ident, $to_endian:ident, $from_endian:ident, $size:expr) => {
24 impl Encoding<$base> for $endian<$base> {
25 const ZERO: Self = Self(0);
26 }
27
28 impl From<[u8; $size]> for $endian<$base> {
29 #[inline]
30 fn from(bytes: [u8; $size]) -> Self {
31 Self($base::from_ne_bytes(bytes))
32 }
33 }
34
35 impl From<$endian<$base>> for [u8; $size] {
36 #[inline]
37 fn from(encoded: $endian<$base>) -> Self {
38 $base::to_ne_bytes(encoded.0)
39 }
40 }
41
42 impl From<$base> for $endian<$base> {
43 #[inline]
44 fn from(value: $base) -> Self {
45 Self($base::$to_endian(value))
46 }
47 }
48
49 impl From<Wrapping<$base>> for $endian<$base> {
50 #[inline]
51 fn from(Wrapping(value): Wrapping<$base>) -> Self {
52 Self($base::$to_endian(value))
53 }
54 }
55
56 impl From<$endian<$base>> for $base {
57 #[inline]
58 fn from($endian(value): $endian<$base>) -> Self {
59 $base::$from_endian(value)
60 }
61 }
62 };
63}
64
65define_endian!(BigEndian);
66impl_endian!(BigEndian, u32, to_be, from_be, 4);
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_big_endian() {
74 let x = BigEndian::from(1u32);
75 assert_eq!(u32::from(x), 1);
76 }
77}
78