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 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 *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 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 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 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}