1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::{mem, ptr};

use light_bounded_vec::{
    BoundedVec, BoundedVecMetadata, CyclicBoundedVec, CyclicBoundedVecMetadata,
};

/// Casts a part of provided `bytes` buffer with the given `offset` to a
/// mutable pointer to `T`.
///
/// Should be used for single values.
///
/// # Safety
///
/// This is higly unsafe. This function doesn't ensure alignment and
/// correctness of provided buffer. The responsibility of such checks is on
/// the caller.
pub unsafe fn read_ptr_at<T>(bytes: &[u8], offset: &mut usize) -> *mut T {
    let size = mem::size_of::<T>();
    let ptr = bytes[*offset..*offset + size].as_ptr() as *mut T;
    *offset += size;
    ptr
}

/// Casts a part of provided `bytes` buffer with the given `offset` to a
/// mutable pointer to `T`.
///
/// Should be used for array-type sequences.
///
/// # Safety
///
/// This is higly unsafe. This function doesn't ensure alignment and
/// correctness of provided buffer. The responsibility of such checks is on
/// the caller.
pub unsafe fn read_array_like_ptr_at<T>(bytes: &[u8], offset: &mut usize, len: usize) -> *mut T {
    let size = mem::size_of::<T>() * len;
    let ptr = bytes[*offset..*offset + size].as_ptr() as *mut T;
    *offset += size;
    ptr
}

/// Creates a copy of value of type `T` based on the provided `bytes` buffer.
///
/// # Safety
///
/// This is higly unsafe. This function doesn't ensure alignment and
/// correctness of provided buffer. The responsibility of such checks is on
/// the caller.
pub unsafe fn read_value_at<T>(bytes: &[u8], offset: &mut usize) -> T
where
    T: Clone,
{
    let size = mem::size_of::<T>();
    let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;
    *offset += size;
    // (*ptr).clone()
    ptr::read(ptr)
}

/// Creates a `BoundedVec` from the sequence of values provided in `bytes` buffer.
///
/// # Safety
///
/// This is higly unsafe. This function doesn't ensure alignment and
/// correctness of provided buffer. The responsibility of such checks is on
/// the caller.
pub unsafe fn read_bounded_vec_at<T>(
    bytes: &[u8],
    offset: &mut usize,
    metadata: &BoundedVecMetadata,
) -> BoundedVec<T>
where
    T: Clone,
{
    let size = mem::size_of::<T>() * metadata.capacity();
    let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;

    let mut vec = BoundedVec::with_capacity(metadata.capacity());
    for i in 0..metadata.length() {
        let val = ptr::read(ptr.add(i));
        // PANICS: We ensured the bounds.
        vec.push(val).unwrap();
    }

    *offset += size;

    vec
}

/// Creates a `CyclicBoundedVec` from the sequence of values provided in
/// `bytes` buffer.
///
/// # Safety
///
/// This is higly unsafe. This function doesn't ensure alignment and
/// correctness of provided buffer. The responsibility of such checks is on
/// the caller.
pub unsafe fn read_cyclic_bounded_vec_at<T>(
    bytes: &[u8],
    offset: &mut usize,
    metadata: &CyclicBoundedVecMetadata,
) -> CyclicBoundedVec<T>
where
    T: Clone,
{
    let size = mem::size_of::<T>() * metadata.capacity();
    let ptr = bytes[*offset..*offset + size].as_ptr() as *const T;

    let mut vec = CyclicBoundedVec::with_capacity(metadata.capacity());
    for i in 0..metadata.length() {
        let val = ptr::read(ptr.add(i));
        vec.push(val);
    }

    *offset += size;

    vec
}

/// Writes provided `data` into provided `bytes` buffer with the given
/// `offset`.
pub fn write_at<T>(bytes: &mut [u8], data: &[u8], offset: &mut usize) {
    let size = mem::size_of::<T>();
    bytes[*offset..*offset + size].copy_from_slice(data);
    *offset += size;
}