simple_endian/
simple_endian.rs

1//! Types that do not change based on endianness.
2//!
3//! This module provides the `SimpleEndian` trait for types that are the same in both big-endian and little-endian
4//! representations. These types are built into Rust, the core crate, and the std crate, and include:
5//! - The unit type `()`
6//! - Boolean values `bool`
7//! - String slices and owned strings (when the `string_impls` feature is enabled)
8//! - Arrays of SimpleEndian types (when the `array_impls` feature is enabled)
9//! - Other single-byte types
10//!
11//! All conversions for types implementing `SimpleEndian` are no-ops since the endianness doesn't affect them.
12
13/// A trait for types that do not change based on endianness.
14///
15/// Types implementing `SimpleEndian` have the same representation regardless of whether they are
16/// stored in big-endian or little-endian byte order. This includes single-byte types, the unit type,
17/// and other endianness-agnostic types.
18///
19/// All conversion methods are no-ops for these types, providing default implementations that simply
20/// return the value unchanged.
21pub trait SimpleEndian: Sized + Clone {
22    /// No-op conversion to big-endian representation (returns self unchanged).
23    fn to_big_endian(self) -> Self {
24        self
25    }
26
27    /// No-op conversion to little-endian representation (returns self unchanged).
28    fn to_little_endian(self) -> Self {
29        self
30    }
31
32    /// No-op conversion from big-endian representation (returns self unchanged).
33    fn from_big_endian(self) -> Self {
34        self
35    }
36
37    /// No-op conversion from little-endian representation (returns self unchanged).
38    fn from_little_endian(self) -> Self {
39        self
40    }
41
42    /// Returns the endianness of the host target.
43    fn endian(&self) -> crate::specific_endian::Endian {
44        if cfg!(target_endian = "big") {
45            crate::specific_endian::Endian::Big
46        } else {
47            crate::specific_endian::Endian::Little
48        }
49    }
50}
51
52/// Implement SimpleEndian for the unit type `()`.
53impl SimpleEndian for () {}
54
55/// Implement SimpleEndian for `bool`.
56#[cfg(feature = "simple_bool")]
57impl SimpleEndian for bool {}
58
59/// Implement SimpleEndian for `u8` (single byte, endianness-independent).
60#[cfg(feature = "simple_byte_impls")]
61impl SimpleEndian for u8 {}
62
63/// Implement SimpleEndian for `i8` (single byte, endianness-independent).
64#[cfg(feature = "simple_byte_impls")]
65impl SimpleEndian for i8 {}
66
67/// Implement SimpleEndian for `char` (a Unicode scalar value; endianness-independent as a Rust value).
68#[cfg(feature = "simple_char_impls")]
69impl SimpleEndian for char {}
70
71/// Implement SimpleEndian for string slices `&str`.
72#[cfg(feature = "simple_string_impls")]
73impl SimpleEndian for &str {}
74
75/// Implement SimpleEndian for owned strings `String`.
76#[cfg(feature = "simple_string_impls")]
77impl SimpleEndian for String {}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn unit_type_is_simple_endian() {
85        let _unit: () = ();
86        assert!(true); // If this compiles, the trait is implemented
87    }
88
89    #[test]
90    #[cfg(feature = "simple_bool")]
91    fn bool_is_simple_endian() {
92        let b = true;
93        assert_eq!(b.to_big_endian(), b);
94        assert_eq!(b.to_little_endian(), b);
95        assert_eq!(b.from_big_endian(), b);
96        assert_eq!(b.from_little_endian(), b);
97    }
98
99    #[test]
100    #[cfg(feature = "simple_byte_impls")]
101    fn u8_is_simple_endian() {
102        let n: u8 = 42;
103        assert_eq!(n.to_big_endian(), n);
104        assert_eq!(n.to_little_endian(), n);
105        assert_eq!(n.from_big_endian(), n);
106        assert_eq!(n.from_little_endian(), n);
107    }
108
109    #[test]
110    #[cfg(feature = "simple_byte_impls")]
111    fn i8_is_simple_endian() {
112        let n: i8 = -42;
113        assert_eq!(n.to_big_endian(), n);
114        assert_eq!(n.to_little_endian(), n);
115        assert_eq!(n.from_big_endian(), n);
116        assert_eq!(n.from_little_endian(), n);
117    }
118
119    #[test]
120    #[cfg(feature = "simple_char_impls")]
121    fn char_is_simple_endian() {
122        let c: char = '🦀';
123        assert_eq!(c.to_big_endian(), c);
124        assert_eq!(c.to_little_endian(), c);
125        assert_eq!(c.from_big_endian(), c);
126        assert_eq!(c.from_little_endian(), c);
127    }
128
129    #[test]
130    #[cfg(feature = "simple_string_impls")]
131    fn str_is_simple_endian() {
132        let s = "hello";
133        assert_eq!(s.to_big_endian(), s);
134        assert_eq!(s.to_little_endian(), s);
135        assert_eq!(s.from_big_endian(), s);
136        assert_eq!(s.from_little_endian(), s);
137    }
138
139    #[test]
140    #[cfg(feature = "simple_string_impls")]
141    fn string_is_simple_endian() {
142        let s = String::from("hello");
143        let converted = s.clone().to_big_endian();
144        assert_eq!(converted, s);
145
146        let converted = s.clone().to_little_endian();
147        assert_eq!(converted, s);
148
149        let converted = s.clone().from_big_endian();
150        assert_eq!(converted, s);
151
152        let converted = s.clone().from_little_endian();
153        assert_eq!(converted, s);
154    }
155}