light_concurrent_merkle_tree/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/// Casts a part of provided `bytes` buffer with the given `offset` to a
38/// mutable pointer to `T`.
39///
40/// Should be used for array-type sequences.
41///
42/// # Safety
43///
44/// This is higly unsafe. This function doesn't ensure alignment and
45/// correctness of provided buffer. The responsibility of such checks is on
46/// the caller.
47pub 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
58/// Writes provided `data` into provided `bytes` buffer with the given
59/// `offset`.
60pub 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}