1use std::mem;
2
3pub unsafe fn read_ptr_at<T>(bytes: &[u8], offset: &mut usize) -> *mut T {
14 let size = mem::size_of::<T>();
15 let ptr = bytes[*offset..*offset + size].as_ptr() as *mut T;
16 *offset += size;
17 ptr
18}
19
20pub unsafe fn read_array_like_ptr_at<T>(bytes: &[u8], offset: &mut usize, len: usize) -> *mut T {
31 let size = mem::size_of::<T>() * len;
32 let ptr = bytes[*offset..*offset + size].as_ptr() as *mut T;
33 *offset += size;
34 ptr
35}
36
37pub fn write_at<T>(bytes: &mut [u8], data: &[u8], offset: &mut usize) {
40 let size = mem::size_of::<T>();
41 bytes[*offset..*offset + size].copy_from_slice(data);
42 *offset += size;
43}
44
45#[cfg(test)]
46mod test {
47 use super::*;
48
49 use bytemuck::{Pod, Zeroable};
50 use memoffset::offset_of;
51
52 #[test]
53 fn test_read_ptr_at() {
54 #[derive(Clone, Copy, Pod, Zeroable)]
55 #[repr(C)]
56 struct TestStruct {
57 a: isize,
58 b: usize,
59 c: i64,
60 d: u64,
61 e: i32,
62 f: u32,
63 g: i16,
64 _padding_1: [u8; 2],
65 h: u16,
66 _padding_2: [u8; 2],
67 i: i8,
68 _padding_3: [i8; 3],
69 j: u8,
70 _padding_4: [i8; 3],
71 }
72
73 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
74 let s = buf.as_mut_ptr() as *mut TestStruct;
75
76 unsafe {
77 (*s).a = isize::MIN;
78 (*s).b = usize::MAX;
79 (*s).c = i64::MIN;
80 (*s).d = u64::MAX;
81 (*s).e = i32::MIN;
82 (*s).f = u32::MAX;
83 (*s).g = i16::MIN;
84 (*s).h = u16::MAX;
85 (*s).i = i8::MIN;
86 (*s).j = u8::MAX;
87
88 let mut offset = offset_of!(TestStruct, a);
89 assert_eq!(offset, 0);
90 assert_eq!(*read_ptr_at::<isize>(&buf, &mut offset), isize::MIN);
91 assert_eq!(offset, 8);
92
93 let mut offset = offset_of!(TestStruct, b);
94 assert_eq!(offset, 8);
95 assert_eq!(*read_ptr_at::<usize>(&buf, &mut offset), usize::MAX);
96 assert_eq!(offset, 16);
97
98 let mut offset = offset_of!(TestStruct, c);
99 assert_eq!(offset, 16);
100 assert_eq!(*read_ptr_at::<i64>(&buf, &mut offset), i64::MIN);
101 assert_eq!(offset, 24);
102
103 let mut offset = offset_of!(TestStruct, d);
104 assert_eq!(offset, 24);
105 assert_eq!(*read_ptr_at::<u64>(&buf, &mut offset), u64::MAX);
106 assert_eq!(offset, 32);
107
108 let mut offset = offset_of!(TestStruct, e);
109 assert_eq!(offset, 32);
110 assert_eq!(*read_ptr_at::<i32>(&buf, &mut offset), i32::MIN);
111 assert_eq!(offset, 36);
112
113 let mut offset = offset_of!(TestStruct, f);
114 assert_eq!(offset, 36);
115 assert_eq!(*read_ptr_at::<u32>(&buf, &mut offset), u32::MAX);
116 assert_eq!(offset, 40);
117
118 let mut offset = offset_of!(TestStruct, g);
119 assert_eq!(offset, 40);
120 assert_eq!(*read_ptr_at::<i16>(&buf, &mut offset), i16::MIN);
121 assert_eq!(offset, 42);
122
123 let mut offset = offset_of!(TestStruct, h);
124 assert_eq!(offset, 44);
125 assert_eq!(*read_ptr_at::<u16>(&buf, &mut offset), u16::MAX);
126 assert_eq!(offset, 46);
127
128 let mut offset = offset_of!(TestStruct, i);
129 assert_eq!(offset, 48);
130 assert_eq!(*read_ptr_at::<i8>(&buf, &mut offset), i8::MIN);
131 assert_eq!(offset, 49);
132
133 let mut offset = offset_of!(TestStruct, j);
134 assert_eq!(offset, 52);
135 assert_eq!(*read_ptr_at::<u8>(&buf, &mut offset), u8::MAX);
136 assert_eq!(offset, 53);
137 }
138 }
139
140 #[test]
141 fn test_read_array_like_ptr_at() {
142 #[derive(Clone, Copy, Pod, Zeroable)]
143 #[repr(C)]
144 struct TestStruct {
145 a: [i64; 32],
146 b: [u64; 32],
147 }
148
149 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
150 let s = buf.as_mut_ptr() as *mut TestStruct;
151
152 unsafe {
153 for (i, element) in (*s).a.iter_mut().enumerate() {
154 *element = -(i as i64);
155 }
156 for (i, element) in (*s).b.iter_mut().enumerate() {
157 *element = i as u64;
158 }
159
160 let mut offset = offset_of!(TestStruct, a);
161 assert_eq!(offset, 0);
162 let ptr: *mut i64 = read_array_like_ptr_at(&buf, &mut offset, 32);
163 for i in 0..32 {
164 assert_eq!(*(ptr.add(i)), -(i as i64));
165 }
166 assert_eq!(offset, 256);
167
168 let mut offset = offset_of!(TestStruct, b);
169 assert_eq!(offset, 256);
170 let ptr: *mut u64 = read_array_like_ptr_at(&buf, &mut offset, 32);
171 for i in 0..32 {
172 assert_eq!(*(ptr.add(i)), i as u64);
173 }
174 assert_eq!(offset, 512);
175 }
176 }
177
178 #[test]
179 fn test_write_at() {
180 #[derive(Clone, Copy, Pod, Zeroable)]
181 #[repr(C)]
182 struct TestStruct {
183 a: isize,
184 b: usize,
185 c: i64,
186 d: u64,
187 e: i32,
188 f: u32,
189 g: i16,
190 _padding_1: [u8; 2],
191 h: u16,
192 _padding_2: [u8; 2],
193 i: i8,
194 _padding_3: [i8; 3],
195 j: u8,
196 _padding_4: [i8; 3],
197 }
198
199 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
200
201 let a: isize = isize::MIN;
202 let b: usize = usize::MAX;
203 let c: i64 = i64::MIN;
204 let d: u64 = u64::MAX;
205 let e: i32 = i32::MIN;
206 let f: u32 = u32::MAX;
207 let g: i16 = i16::MIN;
208 let h: u16 = u16::MAX;
209 let i: i8 = i8::MIN;
210 let j: u8 = u8::MAX;
211
212 let mut offset = offset_of!(TestStruct, a);
213 assert_eq!(offset, 0);
214 write_at::<isize>(&mut buf, &a.to_le_bytes(), &mut offset);
215 assert_eq!(offset, 8);
216
217 let mut offset = offset_of!(TestStruct, b);
218 assert_eq!(offset, 8);
219 write_at::<usize>(&mut buf, &b.to_le_bytes(), &mut offset);
220 assert_eq!(offset, 16);
221
222 let mut offset = offset_of!(TestStruct, c);
223 assert_eq!(offset, 16);
224 write_at::<i64>(&mut buf, &c.to_le_bytes(), &mut offset);
225 assert_eq!(offset, 24);
226
227 let mut offset = offset_of!(TestStruct, d);
228 assert_eq!(offset, 24);
229 write_at::<u64>(&mut buf, &d.to_le_bytes(), &mut offset);
230 assert_eq!(offset, 32);
231
232 let mut offset = offset_of!(TestStruct, e);
233 assert_eq!(offset, 32);
234 write_at::<i32>(&mut buf, &e.to_le_bytes(), &mut offset);
235 assert_eq!(offset, 36);
236
237 let mut offset = offset_of!(TestStruct, f);
238 assert_eq!(offset, 36);
239 write_at::<u32>(&mut buf, &f.to_le_bytes(), &mut offset);
240 assert_eq!(offset, 40);
241
242 let mut offset = offset_of!(TestStruct, g);
243 assert_eq!(offset, 40);
244 write_at::<i16>(&mut buf, &g.to_le_bytes(), &mut offset);
245 assert_eq!(offset, 42);
246
247 let mut offset = offset_of!(TestStruct, h);
248 assert_eq!(offset, 44);
249 write_at::<u16>(&mut buf, &h.to_le_bytes(), &mut offset);
250 assert_eq!(offset, 46);
251
252 let mut offset = offset_of!(TestStruct, i);
253 assert_eq!(offset, 48);
254 write_at::<i8>(&mut buf, &i.to_le_bytes(), &mut offset);
255 assert_eq!(offset, 49);
256
257 let mut offset = offset_of!(TestStruct, j);
258 assert_eq!(offset, 52);
259 write_at::<u8>(&mut buf, &j.to_le_bytes(), &mut offset);
260 assert_eq!(offset, 53);
261
262 let s = buf.as_mut_ptr() as *mut TestStruct;
263
264 unsafe {
265 assert_eq!((*s).a, a);
266 assert_eq!((*s).b, b);
267 assert_eq!((*s).c, c);
268 assert_eq!((*s).d, d);
269 assert_eq!((*s).e, e);
270 assert_eq!((*s).f, f);
271 assert_eq!((*s).g, g);
272 assert_eq!((*s).h, h);
273 assert_eq!((*s).i, i);
274 assert_eq!((*s).j, j);
275 }
276 }
277}