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 unsafe fn read_array_like_ptr_at_mut<T>(
48 bytes: &mut [u8],
49 offset: &mut usize,
50 len: usize,
51) -> *mut T {
52 let size = mem::size_of::<T>() * len;
53 let ptr = bytes[*offset..*offset + size].as_ptr() as *mut T;
54 *offset += size;
55 ptr
56}
57
58pub fn write_at<T>(bytes: &mut [u8], data: &[u8], offset: &mut usize) {
61 let size = mem::size_of::<T>();
62 bytes[*offset..*offset + size].copy_from_slice(data);
63 *offset += size;
64}
65
66#[cfg(test)]
67mod test {
68 use memoffset::offset_of;
69
70 use super::*;
71
72 #[test]
73 fn test_read_ptr_at() {
74 #[derive(Clone, Copy)]
75 #[repr(C)]
76 struct TestStruct {
77 a: isize,
78 b: usize,
79 c: i64,
80 d: u64,
81 e: i32,
82 f: u32,
83 g: i16,
84 _padding_1: [u8; 2],
85 h: u16,
86 _padding_2: [u8; 2],
87 i: i8,
88 _padding_3: [i8; 3],
89 j: u8,
90 _padding_4: [i8; 3],
91 }
92
93 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
94 let s = buf.as_mut_ptr() as *mut TestStruct;
95
96 unsafe {
97 (*s).a = isize::MIN;
98 (*s).b = usize::MAX;
99 (*s).c = i64::MIN;
100 (*s).d = u64::MAX;
101 (*s).e = i32::MIN;
102 (*s).f = u32::MAX;
103 (*s).g = i16::MIN;
104 (*s).h = u16::MAX;
105 (*s).i = i8::MIN;
106 (*s).j = u8::MAX;
107
108 let mut offset = offset_of!(TestStruct, a);
109 assert_eq!(offset, 0);
110 assert_eq!(*read_ptr_at::<isize>(&buf, &mut offset), isize::MIN);
111 assert_eq!(offset, 8);
112
113 let mut offset = offset_of!(TestStruct, b);
114 assert_eq!(offset, 8);
115 assert_eq!(*read_ptr_at::<usize>(&buf, &mut offset), usize::MAX);
116 assert_eq!(offset, 16);
117
118 let mut offset = offset_of!(TestStruct, c);
119 assert_eq!(offset, 16);
120 assert_eq!(*read_ptr_at::<i64>(&buf, &mut offset), i64::MIN);
121 assert_eq!(offset, 24);
122
123 let mut offset = offset_of!(TestStruct, d);
124 assert_eq!(offset, 24);
125 assert_eq!(*read_ptr_at::<u64>(&buf, &mut offset), u64::MAX);
126 assert_eq!(offset, 32);
127
128 let mut offset = offset_of!(TestStruct, e);
129 assert_eq!(offset, 32);
130 assert_eq!(*read_ptr_at::<i32>(&buf, &mut offset), i32::MIN);
131 assert_eq!(offset, 36);
132
133 let mut offset = offset_of!(TestStruct, f);
134 assert_eq!(offset, 36);
135 assert_eq!(*read_ptr_at::<u32>(&buf, &mut offset), u32::MAX);
136 assert_eq!(offset, 40);
137
138 let mut offset = offset_of!(TestStruct, g);
139 assert_eq!(offset, 40);
140 assert_eq!(*read_ptr_at::<i16>(&buf, &mut offset), i16::MIN);
141 assert_eq!(offset, 42);
142
143 let mut offset = offset_of!(TestStruct, h);
144 assert_eq!(offset, 44);
145 assert_eq!(*read_ptr_at::<u16>(&buf, &mut offset), u16::MAX);
146 assert_eq!(offset, 46);
147
148 let mut offset = offset_of!(TestStruct, i);
149 assert_eq!(offset, 48);
150 assert_eq!(*read_ptr_at::<i8>(&buf, &mut offset), i8::MIN);
151 assert_eq!(offset, 49);
152
153 let mut offset = offset_of!(TestStruct, j);
154 assert_eq!(offset, 52);
155 assert_eq!(*read_ptr_at::<u8>(&buf, &mut offset), u8::MAX);
156 assert_eq!(offset, 53);
157 }
158 }
159
160 #[test]
161 fn test_read_array_like_ptr_at() {
162 #[derive(Clone, Copy)]
163 #[repr(C)]
164 struct TestStruct {
165 a: [i64; 32],
166 b: [u64; 32],
167 }
168
169 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
170 let s = buf.as_mut_ptr() as *mut TestStruct;
171
172 unsafe {
173 for (i, element) in (*s).a.iter_mut().enumerate() {
174 *element = -(i as i64);
175 }
176 for (i, element) in (*s).b.iter_mut().enumerate() {
177 *element = i as u64;
178 }
179
180 let mut offset = offset_of!(TestStruct, a);
181 assert_eq!(offset, 0);
182 let ptr: *mut i64 = read_array_like_ptr_at(&buf, &mut offset, 32);
183 for i in 0..32 {
184 assert_eq!(*(ptr.add(i)), -(i as i64));
185 }
186 assert_eq!(offset, 256);
187
188 let mut offset = offset_of!(TestStruct, b);
189 assert_eq!(offset, 256);
190 let ptr: *mut u64 = read_array_like_ptr_at(&buf, &mut offset, 32);
191 for i in 0..32 {
192 assert_eq!(*(ptr.add(i)), i as u64);
193 }
194 assert_eq!(offset, 512);
195 }
196 }
197
198 #[test]
199 fn test_read_array_like_ptr_at_mut() {
200 #[derive(Clone, Copy)]
201 #[repr(C)]
202 struct TestStruct {
203 a: [i64; 32],
204 b: [u64; 32],
205 }
206
207 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
208 let s = buf.as_mut_ptr() as *mut TestStruct;
209
210 unsafe {
211 for (i, element) in (*s).a.iter_mut().enumerate() {
212 *element = -(i as i64);
213 }
214 for (i, element) in (*s).b.iter_mut().enumerate() {
215 *element = i as u64;
216 }
217
218 let mut offset = offset_of!(TestStruct, a);
219 assert_eq!(offset, 0);
220 let ptr: *mut i64 = read_array_like_ptr_at_mut(&mut buf, &mut offset, 32);
221 for i in 0..32 {
222 assert_eq!(*(ptr.add(i)), -(i as i64));
223 }
224 assert_eq!(offset, 256);
225
226 let mut offset = offset_of!(TestStruct, b);
227 assert_eq!(offset, 256);
228 let ptr: *mut u64 = read_array_like_ptr_at_mut(&mut buf, &mut offset, 32);
229 for i in 0..32 {
230 assert_eq!(*(ptr.add(i)), i as u64);
231 }
232 assert_eq!(offset, 512);
233 }
234 }
235
236 #[test]
237 fn test_write_at() {
238 #[derive(Clone, Copy)]
239 #[repr(C)]
240 struct TestStruct {
241 a: isize,
242 b: usize,
243 c: i64,
244 d: u64,
245 e: i32,
246 f: u32,
247 g: i16,
248 _padding_1: [u8; 2],
249 h: u16,
250 _padding_2: [u8; 2],
251 i: i8,
252 _padding_3: [i8; 3],
253 j: u8,
254 _padding_4: [i8; 3],
255 }
256
257 let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
258
259 let a: isize = isize::MIN;
260 let b: usize = usize::MAX;
261 let c: i64 = i64::MIN;
262 let d: u64 = u64::MAX;
263 let e: i32 = i32::MIN;
264 let f: u32 = u32::MAX;
265 let g: i16 = i16::MIN;
266 let h: u16 = u16::MAX;
267 let i: i8 = i8::MIN;
268 let j: u8 = u8::MAX;
269
270 let mut offset = offset_of!(TestStruct, a);
271 assert_eq!(offset, 0);
272 write_at::<isize>(&mut buf, &a.to_le_bytes(), &mut offset);
273 assert_eq!(offset, 8);
274
275 let mut offset = offset_of!(TestStruct, b);
276 assert_eq!(offset, 8);
277 write_at::<usize>(&mut buf, &b.to_le_bytes(), &mut offset);
278 assert_eq!(offset, 16);
279
280 let mut offset = offset_of!(TestStruct, c);
281 assert_eq!(offset, 16);
282 write_at::<i64>(&mut buf, &c.to_le_bytes(), &mut offset);
283 assert_eq!(offset, 24);
284
285 let mut offset = offset_of!(TestStruct, d);
286 assert_eq!(offset, 24);
287 write_at::<u64>(&mut buf, &d.to_le_bytes(), &mut offset);
288 assert_eq!(offset, 32);
289
290 let mut offset = offset_of!(TestStruct, e);
291 assert_eq!(offset, 32);
292 write_at::<i32>(&mut buf, &e.to_le_bytes(), &mut offset);
293 assert_eq!(offset, 36);
294
295 let mut offset = offset_of!(TestStruct, f);
296 assert_eq!(offset, 36);
297 write_at::<u32>(&mut buf, &f.to_le_bytes(), &mut offset);
298 assert_eq!(offset, 40);
299
300 let mut offset = offset_of!(TestStruct, g);
301 assert_eq!(offset, 40);
302 write_at::<i16>(&mut buf, &g.to_le_bytes(), &mut offset);
303 assert_eq!(offset, 42);
304
305 let mut offset = offset_of!(TestStruct, h);
306 assert_eq!(offset, 44);
307 write_at::<u16>(&mut buf, &h.to_le_bytes(), &mut offset);
308 assert_eq!(offset, 46);
309
310 let mut offset = offset_of!(TestStruct, i);
311 assert_eq!(offset, 48);
312 write_at::<i8>(&mut buf, &i.to_le_bytes(), &mut offset);
313 assert_eq!(offset, 49);
314
315 let mut offset = offset_of!(TestStruct, j);
316 assert_eq!(offset, 52);
317 write_at::<u8>(&mut buf, &j.to_le_bytes(), &mut offset);
318 assert_eq!(offset, 53);
319
320 let s = buf.as_mut_ptr() as *mut TestStruct;
321
322 unsafe {
323 assert_eq!((*s).a, a);
324 assert_eq!((*s).b, b);
325 assert_eq!((*s).c, c);
326 assert_eq!((*s).d, d);
327 assert_eq!((*s).e, e);
328 assert_eq!((*s).f, f);
329 assert_eq!((*s).g, g);
330 assert_eq!((*s).h, h);
331 assert_eq!((*s).i, i);
332 assert_eq!((*s).j, j);
333 }
334 }
335}