light_utils/offset/
zero_copy.rs

1use std::mem;
2
3/// Casts a part of provided `bytes` buffer with the given `offset` to a
4/// mutable pointer to `T`.
5///
6/// Should be used for single values.
7///
8/// # Safety
9///
10/// This is higly unsafe. This function doesn't ensure alignment and
11/// correctness of provided buffer. The responsibility of such checks is on
12/// the caller.
13pub 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
20/// Casts a part of provided `bytes` buffer with the given `offset` to a
21/// mutable pointer to `T`.
22///
23/// Should be used for array-type sequences.
24///
25/// # Safety
26///
27/// This is higly unsafe. This function doesn't ensure alignment and
28/// correctness of provided buffer. The responsibility of such checks is on
29/// the caller.
30pub 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
37/// Writes provided `data` into provided `bytes` buffer with the given
38/// `offset`.
39pub 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}