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., `i8`, `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 selected types
42impl_byterep!(i8);
43impl_byterep!(u16);
44impl_byterep!(u32);
45
46/// A generic function that prints multiple memory-level representations
47/// of a numeric value, including binary, little-endian, and big-endian formats.
48///
49/// It supports:
50/// - Binary view
51/// - Little-endian byte array and hex
52/// - Big-endian byte array and hex
53///
54/// # Requirements:
55/// - The type must implement `Display`, `Binary`, `Copy`, and `ByteRepr`.
56///
57/// # Color Codes (Terminal):
58/// - Binary: Red
59/// - LE Bytes: Green
60/// - LE Hex: Yellow
61/// - BE Bytes: Blue
62/// - BE Hex: Magenta
63///
64/// # Examples
65///
66/// ```rust
67/// use byte_repr::represent;
68///
69/// let val = 42u16;
70/// represent(&val); // Should print representations to stdout
71/// ```
72pub fn represent<T>(value: &T)
73where
74    T: std::fmt::Display + std::fmt::Binary + Copy,
75    T: ByteRepr,
76{
77    println!(
78        "\n\nHello, Representing in following formats for: {} \x1b[33m({})\x1b[0m",
79        value,
80        type_name::<T>()
81    );
82
83    // Binary
84    println!(
85        "\x1b[31m Binary representation                      : {:b} \x1b[0m",
86        value
87    );
88
89    // Little-endian bytes
90    println!(
91        "\x1b[32m Little-endian byte array                   : {:?} \x1b[0m",
92        value.to_le_bytes()
93    );
94    println!(
95        "\x1b[33m Hex memory (LE) with 2-digit zero padding  : {:02x?} \x1b[0m",
96        value.to_le_bytes()
97    );
98
99    // Big-endian bytes
100    println!(
101        "\x1b[34m Big-endian byte array                      : {:?} \x1b[0m",
102        value.to_be_bytes()
103    );
104    println!(
105        "\x1b[35m Hex memory (BE) with 2-digit zero padding  : {:02x?} \x1b[0m",
106        value.to_be_bytes()
107    );
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_byte_repr_trait_for_i8() {
116        let val: i8 = 0x12;
117        let expected_le = val.to_le_bytes().to_vec();
118        let expected_be = val.to_be_bytes().to_vec();
119        assert_eq!(ByteRepr::to_le_bytes(&val), expected_le);
120        assert_eq!(ByteRepr::to_be_bytes(&val), expected_be);
121    }
122    #[test]
123    fn test_byte_repr_trait_for_i8_negetive_127() {
124        let val: i8 = -127;
125        let expected_le = val.to_le_bytes().to_vec();
126        let expected_be = val.to_be_bytes().to_vec();
127        assert_eq!(ByteRepr::to_le_bytes(&val), expected_le);
128        assert_eq!(ByteRepr::to_be_bytes(&val), expected_be);
129    }
130    #[test]
131    fn test_byte_repr_trait_for_u16() {
132        let val: u16 = 0x1234;
133        let expected_le = val.to_le_bytes().to_vec();
134        let expected_be = val.to_be_bytes().to_vec();
135        assert_eq!(ByteRepr::to_le_bytes(&val), expected_le);
136        assert_eq!(ByteRepr::to_be_bytes(&val), expected_be);
137    }
138
139    #[test]
140    fn test_byte_repr_trait_for_u32() {
141        let val: u32 = 0x123456;
142        let expected_le = val.to_le_bytes().to_vec();
143        let expected_be = val.to_be_bytes().to_vec();
144        assert_eq!(ByteRepr::to_le_bytes(&val), expected_le);
145        assert_eq!(ByteRepr::to_be_bytes(&val), expected_be);
146    }
147
148    #[test]
149    fn test_represent_does_not_panic() {
150        let val: i8 = 127;
151        represent(&val);
152        let val: i8 = -127;
153        represent(&val);
154        let val: u16 = 65535;
155        represent(&val);
156        let val: u32 = 4294967295;
157        represent(&val);
158    }
159}