byte_repr/
lib.rs

1use std::any::type_name;
2
3/// A trait to extract little-endian and big-endian byte representations
4/// for any type that supports `to_le_bytes()` and `to_be_bytes()`.
5///
6/// # Examples
7///
8/// ```rust
9/// use byte_repr::ByteRepr;
10///
11/// let num: u32 = 0x01020304;
12/// assert_eq!(num.to_le_bytes().to_vec(), vec![0x04, 0x03, 0x02, 0x01]);
13/// assert_eq!(num.to_be_bytes().to_vec(), vec![0x01, 0x02, 0x03, 0x04]);
14/// ```
15pub trait ByteRepr {
16    /// Returns the little-endian byte representation of the value as a `Vec<u8>`.
17    fn to_le_bytes(&self) -> Vec<u8>;
18
19    /// Returns the big-endian byte representation of the value as a `Vec<u8>`.
20    fn to_be_bytes(&self) -> Vec<u8>;
21}
22
23/// A macro to implement the `ByteRepr` trait for primitive numeric types
24/// (e.g., `u8`, `u16`, `u32`, `f64`, etc.).
25///
26/// It uses the type's built-in methods `to_le_bytes()` and `to_be_bytes()`
27/// and converts the resulting fixed-size byte arrays into dynamic vectors.
28macro_rules! impl_byterep {
29    ($t:ty) => {
30        impl ByteRepr for $t {
31            fn to_le_bytes(&self) -> Vec<u8> {
32                <$t>::to_le_bytes(*self).to_vec()
33            }
34            fn to_be_bytes(&self) -> Vec<u8> {
35                <$t>::to_be_bytes(*self).to_vec()
36            }
37        }
38    };
39}
40
41// Implement ByteRepr for all unsigned integer types
42impl_byterep!(u8);
43impl_byterep!(u16);
44impl_byterep!(u32);
45impl_byterep!(u64);
46impl_byterep!(u128);
47impl_byterep!(usize);
48
49/// A generic function that prints multiple memory-level representations
50/// of a numeric value, including binary, little-endian, and big-endian formats.
51///
52/// It supports:
53/// - Binary view
54/// - Little-endian byte array and hex
55/// - Big-endian byte array and hex
56///
57/// # Requirements:
58/// - The type must implement `Display`, `Binary`, `Copy`, and `ByteRepr`.
59///
60/// # Color Codes (Terminal):
61/// - Binary: Red
62/// - LE Bytes: Green
63/// - LE Hex: Yellow
64/// - BE Bytes: Blue
65/// - BE Hex: Magenta
66///
67/// # Examples
68///
69/// ```rust
70/// use byte_repr::represent;
71///     let x = 255u8;
72///     represent(&x);
73///
74///     let x = 65535u16;
75///     represent(&x);
76///
77///     let x = 4294967295u32;
78///     represent(&x);
79///
80///     let x = 18446744073709551615u64;
81///     represent(&x);
82///
83///     let x = 340282366920938463463374607431768211455u128;
84///     represent(&x);
85///
86///     let x = 18446744073709551615usize;
87///     represent(&x);
88/// ```
89pub fn represent<T>(value: &T)
90where
91    T: std::fmt::Display + std::fmt::Binary + Copy,
92    T: ByteRepr,
93{
94    println!(
95        "\n\nHello, Representing in following formats for: {} \x1b[33m({})\x1b[0m",
96        value,
97        type_name::<T>()
98    );
99
100    // Binary
101    println!(
102        "\x1b[31m Binary representation                      : {:b} \x1b[0m",
103        value
104    );
105
106    // Little-endian bytes
107    println!(
108        "\x1b[32m Little-endian byte array                   : {:?} \x1b[0m",
109        value.to_le_bytes()
110    );
111    println!(
112        "\x1b[33m Hex memory (LE) with 2-digit zero padding  : {:02x?} \x1b[0m",
113        value.to_le_bytes()
114    );
115
116    // Big-endian bytes
117    println!(
118        "\x1b[34m Big-endian byte array                      : {:?} \x1b[0m",
119        value.to_be_bytes()
120    );
121    println!(
122        "\x1b[35m Hex memory (BE) with 2-digit zero padding  : {:02x?} \x1b[0m",
123        value.to_be_bytes()
124    );
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130
131    macro_rules! test_unsigned {
132        ($name:ident, $ty:ty, $val:expr) => {
133            #[test]
134            fn $name() {
135                let val: $ty = $val;
136                let expected_le = val.to_le_bytes().to_vec();
137                let expected_be = val.to_be_bytes().to_vec();
138                assert_eq!(ByteRepr::to_le_bytes(&val), expected_le);
139                assert_eq!(ByteRepr::to_be_bytes(&val), expected_be);
140            }
141        };
142    }
143
144    test_unsigned!(test_u8, u8, 0x12);
145    test_unsigned!(test_u16, u16, 0x1234);
146    test_unsigned!(test_u32, u32, 0x12345678);
147    test_unsigned!(test_u64, u64, 0x1234567890abcdef);
148    test_unsigned!(test_u128, u128, 0x1234567890abcdef1122334455667788);
149    test_unsigned!(test_usize, usize, 0x1234);
150
151    #[test]
152    fn test_represent_does_not_panic() {
153        represent(&42u8);
154        represent(&42u16);
155        represent(&42u32);
156        represent(&42u64);
157        represent(&42u128);
158        represent(&42usize);
159    }
160}