shared/
any.rs

1use core::slice;
2
3#[repr(transparent)]
4#[derive(Debug, PartialEq, Eq)]
5pub struct AnyByLayout([u8]);
6
7impl<'a, T> From<&'a mut T> for &'a mut AnyByLayout {
8    fn from(argument: &'a mut T) -> Self {
9        AnyByLayout::from_mutable(argument)
10    }
11}
12
13impl<'a, T> From<&'a T> for &'a AnyByLayout {
14    fn from(argument: &'a T) -> Self {
15        AnyByLayout::from(argument)
16    }
17}
18
19impl AnyByLayout {
20    pub const NONE: &mut Self = Self::from_mutable(&mut [0u8; 0]);
21
22    /// Creates an `AnyByLayout` from raw parts.
23    ///
24    /// # Safety
25    ///
26    /// This function is unsafe because it creates a reference from a raw pointer.
27    /// The caller must ensure that the pointer is valid for reads and writes
28    /// for `size` bytes and properly aligned.
29    pub unsafe fn from_raw_parts<'a>(data: *mut u8, size: usize) -> &'a mut Self {
30        unsafe {
31            let slice = slice::from_raw_parts_mut(data, size);
32            &mut *(slice as *mut [u8] as *mut Self)
33        }
34    }
35
36    pub const fn from_mutable<T>(argument: &mut T) -> &mut Self {
37        unsafe {
38            let slice = slice::from_raw_parts_mut(argument as *mut T as *mut u8, size_of::<T>());
39            &mut *(slice as *mut [u8] as *mut Self)
40        }
41    }
42
43    pub fn from<T>(argument: &T) -> &Self {
44        unsafe {
45            let slice = slice::from_raw_parts(argument as *const T as *const u8, size_of::<T>());
46            &*(slice as *const [u8] as *const Self)
47        }
48    }
49
50    pub fn cast_mutable<T>(&mut self) -> Option<&mut T> {
51        let (prefix, value, suffix) = unsafe { self.0.align_to_mut::<T>() };
52
53        if !prefix.is_empty() && !suffix.is_empty() && value.len() != 1 {
54            return None;
55        }
56
57        value.get_mut(0)
58    }
59
60    pub fn cast<T>(&self) -> Option<&T> {
61        let (prefix, value, suffix) = unsafe { self.0.align_to::<T>() };
62
63        if !prefix.is_empty() && !suffix.is_empty() && value.len() != 1 {
64            return None;
65        }
66
67        value.first()
68    }
69
70    pub fn get_size(&self) -> usize {
71        self.0.len()
72    }
73
74    pub fn get_alignment(&self) -> usize {
75        self.0.as_ptr().align_offset(1)
76    }
77
78    pub fn as_mutable_bytes(&mut self) -> &mut [u8] {
79        &mut self.0
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    extern crate alloc;
86    use super::*;
87    use alloc::vec;
88
89    #[test]
90    fn test_from_mutable_primitive() {
91        let mut value: u32 = 42;
92        let any = AnyByLayout::from_mutable(&mut value);
93
94        assert_eq!(any.get_size(), size_of::<u32>());
95        assert_eq!(any.as_mutable_bytes(), &[42, 0, 0, 0]);
96    }
97
98    #[test]
99    fn test_from_immutable_primitive() {
100        let value: u64 = 0x0102030405060708;
101        let any = AnyByLayout::from(&value);
102
103        assert_eq!(any.get_size(), size_of::<u64>());
104    }
105
106    #[test]
107    fn test_from_trait_mutable() {
108        let mut value: i32 = -100;
109        let any: &mut AnyByLayout = (&mut value).into();
110
111        assert_eq!(any.get_size(), size_of::<i32>());
112    }
113
114    #[test]
115    fn test_from_trait_immutable() {
116        let value: i16 = 256;
117        let any: &AnyByLayout = (&value).into();
118
119        assert_eq!(any.get_size(), size_of::<i16>());
120    }
121
122    #[test]
123    fn test_cast_mutable_success() {
124        let mut value: u32 = 12345;
125        let any = AnyByLayout::from_mutable(&mut value);
126
127        let cast_back = any.cast_mutable::<u32>();
128        assert!(cast_back.is_some());
129
130        if let Some(cast_ref) = cast_back {
131            assert_eq!(*cast_ref, 12345);
132            // Modify through the cast reference
133            *cast_ref = 67890;
134        }
135        assert_eq!(value, 67890);
136    }
137
138    #[test]
139    fn test_cast_immutable_success() {
140        let value: i64 = -9876543210;
141        let any = AnyByLayout::from(&value);
142
143        let cast_back = any.cast::<i64>();
144        assert!(cast_back.is_some());
145        assert_eq!(*cast_back.unwrap(), -9876543210);
146    }
147
148    #[test]
149    fn test_cast_wrong_type_size() {
150        let value: u32 = 42;
151        let any = AnyByLayout::from(&value);
152
153        // Try to cast u32 (4 bytes) as u64 (8 bytes)
154        let cast_result = any.cast::<u64>();
155        assert!(cast_result.is_none());
156    }
157
158    #[test]
159    fn test_from_raw_parts() {
160        let mut data = vec![1u8, 2, 3, 4, 5, 6, 7, 8];
161        let any = unsafe { AnyByLayout::from_raw_parts(data.as_mut_ptr(), data.len()) };
162
163        assert_eq!(any.get_size(), 8);
164        assert_eq!(any.as_mutable_bytes(), &[1, 2, 3, 4, 5, 6, 7, 8]);
165    }
166
167    #[test]
168    fn test_empty_constant() {
169        let empty = AnyByLayout::NONE;
170        assert_eq!(empty.get_size(), 0);
171    }
172
173    #[test]
174    fn test_as_mutable_bytes_modify() {
175        let mut value: u32 = 0x12345678;
176        let any = AnyByLayout::from_mutable(&mut value);
177
178        let bytes = any.as_mutable_bytes();
179        bytes[0] = 0xFF;
180
181        // Value should be modified
182        assert_eq!(value & 0xFF, 0xFF);
183    }
184
185    #[test]
186    fn test_struct_conversion() {
187        #[derive(Debug, PartialEq, Clone)]
188        struct TestStruct {
189            a: u32,
190            b: u16,
191            c: u8,
192        }
193
194        let mut original = TestStruct {
195            a: 100,
196            b: 200,
197            c: 50,
198        };
199        let expected = original.clone();
200        let any = AnyByLayout::from_mutable(&mut original);
201
202        assert_eq!(any.get_size(), size_of::<TestStruct>());
203
204        let cast_back = any.cast_mutable::<TestStruct>();
205        assert!(cast_back.is_some());
206
207        if let Some(cast_ref) = cast_back {
208            assert_eq!(*cast_ref, expected);
209            // Modify and verify
210            cast_ref.a = 999;
211        }
212        assert_eq!(original.a, 999);
213    }
214
215    #[test]
216    fn test_array_conversion() {
217        let mut array = [1u8, 2, 3, 4, 5];
218        let any = AnyByLayout::from_mutable(&mut array);
219
220        assert_eq!(any.get_size(), 5);
221        assert_eq!(any.as_mutable_bytes(), &[1, 2, 3, 4, 5]);
222
223        let cast_back = any.cast_mutable::<[u8; 5]>();
224        assert!(cast_back.is_some());
225        assert_eq!(*cast_back.unwrap(), [1, 2, 3, 4, 5]);
226    }
227
228    #[test]
229    fn test_zero_sized_type() {
230        let mut unit = ();
231        let any = AnyByLayout::from_mutable(&mut unit);
232
233        assert_eq!(any.get_size(), 0);
234    }
235
236    #[test]
237    fn test_equality() {
238        let value1: u32 = 42;
239        let value2: u32 = 42;
240        let value3: u32 = 43;
241
242        let any1 = AnyByLayout::from(&value1);
243        let any2 = AnyByLayout::from(&value2);
244        let any3 = AnyByLayout::from(&value3);
245
246        assert_eq!(any1, any2);
247        assert_ne!(any1, any3);
248    }
249
250    #[test]
251    fn test_roundtrip_conversion() {
252        let original: f64 = 3.141592653589793;
253        let any = AnyByLayout::from(&original);
254        let cast_back = any.cast::<f64>().unwrap();
255
256        assert_eq!(*cast_back, original);
257    }
258}