light_concurrent_merkle_tree/offset/
copy.rs

1use std::{mem, ptr};
2
3use light_bounded_vec::{
4    BoundedVec, BoundedVecMetadata, CyclicBoundedVec, CyclicBoundedVecMetadata,
5};
6
7/// Creates a copy of value of type `T` based on the provided `bytes` buffer.
8///
9/// # Safety
10///
11/// This is higly unsafe. This function doesn't ensure alignment and
12/// correctness of provided buffer. The responsibility of such checks is on
13/// the caller.
14pub unsafe fn read_value_at<T>(bytes: &[u8], offset: &mut usize) -> T
15where
16    T: Clone,
17{
18    let size = mem::size_of::<T>();
19    let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
20    *offset += size;
21    ptr::read(ptr)
22}
23
24/// Creates a `BoundedVec` from the sequence of values provided in `bytes` buffer.
25///
26/// # Safety
27///
28/// This is higly unsafe. This function doesn't ensure alignment and
29/// correctness of provided buffer. The responsibility of such checks is on
30/// the caller.
31///
32/// The `T` type needs to be either a primitive or struct consisting of
33/// primitives. It cannot contain any nested heap-backed stucture (like vectors,
34/// slices etc.).
35pub unsafe fn read_bounded_vec_at<T>(
36    bytes: &[u8],
37    offset: &mut usize,
38    metadata: &BoundedVecMetadata,
39) -> BoundedVec<T>
40where
41    T: Clone,
42{
43    let size = mem::size_of::<T>() * metadata.capacity();
44    let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
45
46    let mut vec = BoundedVec::with_metadata(metadata);
47    let dst_ptr: *mut T = vec.as_mut_ptr();
48
49    for i in 0..metadata.length() {
50        let val = ptr::read(ptr.add(i));
51        // SAFETY: We ensured the bounds.
52        unsafe { ptr::write(dst_ptr.add(i), val) };
53    }
54
55    *offset += size;
56
57    vec
58}
59
60/// Creates a `CyclicBoundedVec` from the sequence of values provided in
61/// `bytes` buffer.
62///
63/// # Safety
64///
65/// This is higly unsafe. This function doesn't ensure alignment and
66/// correctness of provided buffer. The responsibility of such checks is on
67/// the caller.
68pub unsafe fn read_cyclic_bounded_vec_at<T>(
69    bytes: &[u8],
70    offset: &mut usize,
71    metadata: &CyclicBoundedVecMetadata,
72) -> CyclicBoundedVec<T>
73where
74    T: Clone,
75{
76    let size = mem::size_of::<T>() * metadata.capacity();
77    let src_ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
78
79    let mut vec = CyclicBoundedVec::with_metadata(metadata);
80    let dst_ptr: *mut T = vec.as_mut_ptr();
81
82    for i in 0..metadata.length() {
83        let val = ptr::read(src_ptr.add(i));
84        // SAFETY: We ensured the bounds.
85        unsafe { ptr::write(dst_ptr.add(i), val) };
86    }
87
88    *offset += size;
89
90    vec
91}
92
93#[cfg(test)]
94mod test {
95    use std::slice;
96
97    use memoffset::offset_of;
98
99    use super::*;
100
101    #[test]
102    fn test_value_at() {
103        #[derive(Clone, Copy)]
104        #[repr(C)]
105        struct TestStruct {
106            a: isize,
107            b: usize,
108            c: i64,
109            d: u64,
110            e: i32,
111            f: u32,
112            g: i16,
113            _padding_1: [u8; 2],
114            h: u16,
115            _padding_2: [u8; 2],
116            i: i8,
117            _padding_3: [i8; 3],
118            j: u8,
119            _padding_4: [i8; 3],
120        }
121
122        let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
123        let s = buf.as_mut_ptr() as *mut TestStruct;
124
125        unsafe {
126            (*s).a = isize::MIN;
127            (*s).b = usize::MAX;
128            (*s).c = i64::MIN;
129            (*s).d = u64::MAX;
130            (*s).e = i32::MIN;
131            (*s).f = u32::MAX;
132            (*s).g = i16::MIN;
133            (*s).h = u16::MAX;
134            (*s).i = i8::MIN;
135            (*s).j = u8::MAX;
136
137            let mut offset = offset_of!(TestStruct, a);
138            assert_eq!(offset, 0);
139            assert_eq!(read_value_at::<isize>(&buf, &mut offset), isize::MIN);
140            assert_eq!(offset, 8);
141
142            let mut offset = offset_of!(TestStruct, b);
143            assert_eq!(offset, 8);
144            assert_eq!(read_value_at::<usize>(&buf, &mut offset), usize::MAX);
145            assert_eq!(offset, 16);
146
147            let mut offset = offset_of!(TestStruct, c);
148            assert_eq!(offset, 16);
149            assert_eq!(read_value_at::<i64>(&buf, &mut offset), i64::MIN);
150            assert_eq!(offset, 24);
151
152            let mut offset = offset_of!(TestStruct, d);
153            assert_eq!(offset, 24);
154            assert_eq!(read_value_at::<u64>(&buf, &mut offset), u64::MAX);
155            assert_eq!(offset, 32);
156
157            let mut offset = offset_of!(TestStruct, e);
158            assert_eq!(offset, 32);
159            assert_eq!(read_value_at::<i32>(&buf, &mut offset), i32::MIN);
160            assert_eq!(offset, 36);
161
162            let mut offset = offset_of!(TestStruct, f);
163            assert_eq!(offset, 36);
164            assert_eq!(read_value_at::<u32>(&buf, &mut offset), u32::MAX);
165            assert_eq!(offset, 40);
166
167            let mut offset = offset_of!(TestStruct, g);
168            assert_eq!(offset, 40);
169            assert_eq!(read_value_at::<i16>(&buf, &mut offset), i16::MIN);
170            assert_eq!(offset, 42);
171
172            let mut offset = offset_of!(TestStruct, h);
173            assert_eq!(offset, 44);
174            assert_eq!(read_value_at::<u16>(&buf, &mut offset), u16::MAX);
175            assert_eq!(offset, 46);
176
177            let mut offset = offset_of!(TestStruct, i);
178            assert_eq!(offset, 48);
179            assert_eq!(read_value_at::<i8>(&buf, &mut offset), i8::MIN);
180            assert_eq!(offset, 49);
181
182            let mut offset = offset_of!(TestStruct, j);
183            assert_eq!(offset, 52);
184            assert_eq!(read_value_at::<u8>(&buf, &mut offset), u8::MAX);
185            assert_eq!(offset, 53);
186        }
187    }
188
189    #[test]
190    fn test_read_bounded_vec_at() {
191        #[derive(Clone, Copy)]
192        #[repr(C)]
193        struct TestStruct {
194            a: [i64; 32],
195            b: [u64; 32],
196            c: [[u8; 32]; 32],
197        }
198
199        let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
200        let s = buf.as_mut_ptr() as *mut TestStruct;
201
202        unsafe {
203            for (i, element) in (*s).a.iter_mut().enumerate() {
204                *element = -(i as i64);
205            }
206            for (i, element) in (*s).b.iter_mut().enumerate() {
207                *element = i as u64;
208            }
209            for (i, element) in (*s).c.iter_mut().enumerate() {
210                *element = [i as u8; 32];
211            }
212
213            let metadata = BoundedVecMetadata::new_with_length(32, 32);
214            let mut offset = offset_of!(TestStruct, a);
215            assert_eq!(offset, 0);
216            let vec: BoundedVec<i64> = read_bounded_vec_at(&buf, &mut offset, &metadata);
217            for (i, element) in vec.iter().enumerate() {
218                assert_eq!(i as i64, -*element);
219            }
220            assert_eq!(offset, 256);
221
222            let metadata = BoundedVecMetadata::new_with_length(32, 32);
223            let mut offset = offset_of!(TestStruct, b);
224            assert_eq!(offset, 256);
225            let vec: BoundedVec<u64> = read_bounded_vec_at(&buf, &mut offset, &metadata);
226            for (i, element) in vec.iter().enumerate() {
227                assert_eq!(i as u64, *element);
228            }
229            assert_eq!(offset, 512);
230
231            let metadata = BoundedVecMetadata::new_with_length(32, 32);
232            let mut offset = offset_of!(TestStruct, c);
233            assert_eq!(offset, 512);
234            let vec: BoundedVec<[u8; 32]> = read_bounded_vec_at(&buf, &mut offset, &metadata);
235            for (i, element) in vec.iter().enumerate() {
236                assert_eq!(&[i as u8; 32], element);
237            }
238            assert_eq!(offset, 1536);
239        }
240    }
241
242    #[test]
243    fn test_read_cyclic_bounded_vec_at() {
244        #[derive(Clone, Copy)]
245        #[repr(C)]
246        struct TestStruct {
247            a: [i64; 32],
248            b: [u64; 32],
249            c: [[u8; 32]; 32],
250        }
251
252        let mut buf = vec![0_u8; mem::size_of::<TestStruct>()];
253        let s = buf.as_mut_ptr() as *mut TestStruct;
254
255        unsafe {
256            for (i, element) in (*s).a.iter_mut().enumerate() {
257                *element = -(i as i64);
258            }
259            for (i, element) in (*s).b.iter_mut().enumerate() {
260                *element = i as u64;
261            }
262            for (i, element) in (*s).c.iter_mut().enumerate() {
263                *element = [i as u8; 32];
264            }
265
266            // Start the cyclic vecs from the middle.
267
268            let metadata = CyclicBoundedVecMetadata::new_with_indices(32, 32, 14, 13);
269            let mut offset = offset_of!(TestStruct, a);
270            assert_eq!(offset, 0);
271            let vec: CyclicBoundedVec<i64> =
272                read_cyclic_bounded_vec_at(&buf, &mut offset, &metadata);
273            assert_eq!(vec.capacity(), 32);
274            assert_eq!(vec.len(), 32);
275            assert_eq!(vec.first_index(), 14);
276            assert_eq!(vec.last_index(), 13);
277            assert_eq!(
278                vec.iter().collect::<Vec<_>>().as_slice(),
279                &[
280                    &-14, &-15, &-16, &-17, &-18, &-19, &-20, &-21, &-22, &-23, &-24, &-25, &-26,
281                    &-27, &-28, &-29, &-30, &-31, &-0, &-1, &-2, &-3, &-4, &-5, &-6, &-7, &-8, &-9,
282                    &-10, &-11, &-12, &-13
283                ]
284            );
285            assert_eq!(offset, 256);
286
287            let metadata = CyclicBoundedVecMetadata::new_with_indices(32, 32, 14, 13);
288            let mut offset = offset_of!(TestStruct, b);
289            assert_eq!(offset, 256);
290            let vec: CyclicBoundedVec<u64> =
291                read_cyclic_bounded_vec_at(&buf, &mut offset, &metadata);
292            assert_eq!(vec.capacity(), 32);
293            assert_eq!(vec.len(), 32);
294            assert_eq!(vec.first_index(), 14);
295            assert_eq!(vec.last_index(), 13);
296            assert_eq!(
297                vec.iter().collect::<Vec<_>>().as_slice(),
298                &[
299                    &14, &15, &16, &17, &18, &19, &20, &21, &22, &23, &24, &25, &26, &27, &28, &29,
300                    &30, &31, &0, &1, &2, &3, &4, &5, &6, &7, &8, &9, &10, &11, &12, &13
301                ]
302            );
303            assert_eq!(offset, 512);
304
305            let metadata = CyclicBoundedVecMetadata::new_with_indices(32, 32, 14, 13);
306            let mut offset = offset_of!(TestStruct, c);
307            assert_eq!(offset, 512);
308            let vec: CyclicBoundedVec<[u8; 32]> =
309                read_cyclic_bounded_vec_at(&buf, &mut offset, &metadata);
310            assert_eq!(vec.capacity(), 32);
311            assert_eq!(vec.len(), 32);
312            assert_eq!(vec.first_index(), 14);
313            assert_eq!(vec.last_index(), 13);
314            assert_eq!(
315                vec.iter().collect::<Vec<_>>().as_slice(),
316                &[
317                    &[14_u8; 32],
318                    &[15_u8; 32],
319                    &[16_u8; 32],
320                    &[17_u8; 32],
321                    &[18_u8; 32],
322                    &[19_u8; 32],
323                    &[20_u8; 32],
324                    &[21_u8; 32],
325                    &[22_u8; 32],
326                    &[23_u8; 32],
327                    &[24_u8; 32],
328                    &[25_u8; 32],
329                    &[26_u8; 32],
330                    &[27_u8; 32],
331                    &[28_u8; 32],
332                    &[29_u8; 32],
333                    &[30_u8; 32],
334                    &[31_u8; 32],
335                    &[0_u8; 32],
336                    &[1_u8; 32],
337                    &[2_u8; 32],
338                    &[3_u8; 32],
339                    &[4_u8; 32],
340                    &[5_u8; 32],
341                    &[6_u8; 32],
342                    &[7_u8; 32],
343                    &[8_u8; 32],
344                    &[9_u8; 32],
345                    &[10_u8; 32],
346                    &[11_u8; 32],
347                    &[12_u8; 32],
348                    &[13_u8; 32],
349                ]
350            );
351            assert_eq!(offset, 1536);
352        }
353    }
354
355    #[test]
356    fn test_read_cyclic_bounded_vec_first_last() {
357        let mut vec = CyclicBoundedVec::<u32>::with_capacity(2);
358        vec.push(0);
359        vec.push(37);
360        vec.push(49);
361
362        let metadata_bytes = vec.metadata().to_le_bytes();
363        let metadata = CyclicBoundedVecMetadata::from_le_bytes(metadata_bytes);
364        let bytes = unsafe {
365            slice::from_raw_parts(
366                vec.as_mut_ptr() as *mut u8,
367                mem::size_of::<u32>() * vec.capacity(),
368            )
369        };
370
371        let mut offset = 0;
372        let vec_copy: CyclicBoundedVec<u32> =
373            unsafe { read_cyclic_bounded_vec_at(bytes, &mut offset, &metadata) };
374
375        assert_eq!(*vec.first().unwrap(), 37);
376        assert_eq!(vec.first(), vec_copy.first()); // Fails. Both should be 37
377        assert_eq!(*vec.last().unwrap(), 49);
378        assert_eq!(vec.last(), vec_copy.last()); // Fails. Both should be 49
379    }
380}