ps_mbuf/
lib.rs

1#[repr(C)]
2pub struct Mbuf<'lt, M, D> {
3    metadata: M,
4    length: usize,
5    _marker: std::marker::PhantomData<&'lt D>,
6}
7
8impl<'lt, M, D> Mbuf<'lt, M, D> {
9    pub fn to_slice(&self) -> &[D] {
10        self
11    }
12
13    pub fn to_slice_mut(&mut self) -> &mut [D] {
14        &mut *self
15    }
16
17    pub const fn get_metadata(&self) -> &M {
18        &self.metadata
19    }
20
21    pub fn set_metadata(&mut self, metadata: M) -> M {
22        std::mem::replace(&mut self.metadata, metadata)
23    }
24
25    pub const fn is_empty(&self) -> bool {
26        self.len() == 0
27    }
28
29    pub const fn len(&self) -> usize {
30        self.length
31    }
32}
33
34impl<'lt, M, D> Mbuf<'lt, M, D> {
35    /// Declares an Mbuf begins at a given pointer
36    /// # Safety
37    /// Safe only if the pointer points to a valid Mbuf<'lt, M, D>.
38    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
39    #[must_use]
40    pub const unsafe fn at_ptr(pointer: *const u8) -> &'lt Self {
41        &*pointer.cast::<Mbuf<'lt, M, D>>()
42    }
43
44    /// Declares a mutable Mbuf begins at a given pointer
45    /// # Safety
46    /// Safe only if the pointer points to a valid Mbuf<'lt, M, D> in writable memory.
47    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
48    pub unsafe fn at_ptr_mut(pointer: *mut u8) -> &'lt mut Self {
49        &mut *pointer.cast::<Mbuf<'lt, M, D>>()
50    }
51
52    /// Declares an Mbuf begins at a given byte offset from a given pointer
53    /// # Safety
54    /// Safe only if the the region at (pointer + offset) contains a valid Mbuf<'lt, M, D>.
55    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
56    #[must_use]
57    pub const unsafe fn at_offset(pointer: *const u8, offset: usize) -> &'lt Self {
58        &*(pointer.add(offset)).cast::<Mbuf<'lt, M, D>>()
59    }
60
61    /// Declares a mutable Mbuf begins at a given byte offset from a given pointer
62    /// # Safety
63    /// Safe only if the the region at (pointer + offset) contains a valid Mbuf<'lt, M, D> in writable memory.
64    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
65    pub unsafe fn at_offset_mut(pointer: *mut u8, offset: usize) -> &'lt mut Self {
66        &mut *(pointer.add(offset)).cast::<Mbuf<'lt, M, D>>()
67    }
68
69    /// declares a memory buffer **without data initialization -- items must be initialized by caller**
70    /// # Safety
71    /// Safe if the memory region pointed to is large enough to hold an Mbuf<'lt, M, D> and is writable.
72    /// <br>**Calling this function does not initialize data values in the Mbuf.**
73    /// <br>**Dropping uninitialized data values may be undefined behaviour.**
74    /// <br>Don't do this unless you know what you're doing.
75    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
76    pub unsafe fn init_at_ptr(pointer: *mut u8, metadata: M, length: usize) -> &'lt mut Self {
77        let mbuf = Mbuf::at_ptr_mut(pointer);
78
79        mbuf.metadata = metadata;
80        mbuf.length = length;
81
82        mbuf
83    }
84}
85
86impl<'lt, M, D: Copy> Mbuf<'lt, M, D> {
87    /// Declares an Mbuf at `pointer` and copies `metadata` and `data` into it.
88    /// # Safety
89    /// - `pointer` must point to a large enough place in memory to hold `metadata` + `usize` + `data`.
90    /// - `pointer` must be aligned to at least `usize` and at least `M`.
91    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
92    /// - The memory region at `pointer` must be writable
93    pub unsafe fn write_to_ptr(pointer: *mut u8, metadata: M, data: &[D]) -> &'lt Self {
94        Mbuf::write_to_ptr_mut(pointer, metadata, data)
95    }
96
97    /// Declares a mutable Mbuf at `pointer` and copies `metadata` and `data` into it.
98    /// # Safety
99    /// - `pointer` must point to a large enough place in memory to hold `metadata` + `usize` + `data`.
100    /// - `pointer` must be aligned to at least `usize` and at least `M`.
101    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
102    /// - The memory region at `pointer` must be writable
103    pub unsafe fn write_to_ptr_mut(pointer: *mut u8, metadata: M, data: &[D]) -> &'lt mut Self {
104        let mbuf = Mbuf::init_at_ptr(pointer, metadata, data.len());
105
106        mbuf.copy_from_slice(data);
107
108        mbuf
109    }
110
111    /// Declares an Mbuf at `pointer + offset` and copies `metadata` and `data` into it.
112    /// # Safety
113    /// - `pointer` must point to a large enough place in memory to hold `metadata` + `usize` + `data`.
114    /// - `pointer` must be aligned to at least `usize` and at least `M`.
115    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
116    /// - The memory region at `pointer` must be writable
117    pub unsafe fn write_to_offset(
118        pointer: *mut u8,
119        offset: usize,
120        metadata: M,
121        data: &[D],
122    ) -> &'lt Self {
123        Mbuf::write_to_offset_mut(pointer, offset, metadata, data)
124    }
125
126    /// Declares a mutable Mbuf at `pointer + offset` and copies `metadata` and `data` into it.
127    /// # Safety
128    /// - `pointer` must point to a large enough place in memory to hold `metadata` + `usize` + `data`.
129    /// - `pointer` must be aligned to at least `usize` and at least `M`.
130    /// - The memory region at `pointer` must outlive the returned `&Mbuf`.
131    /// - The memory region at `pointer` must be writable
132    pub unsafe fn write_to_offset_mut(
133        pointer: *mut u8,
134        offset: usize,
135        metadata: M,
136        data: &[D],
137    ) -> &'lt mut Self {
138        Mbuf::write_to_ptr_mut(pointer.add(offset), metadata, data)
139    }
140}
141
142impl<'lt, M, D> AsRef<[D]> for Mbuf<'lt, M, D> {
143    fn as_ref(&self) -> &[D] {
144        self
145    }
146}
147
148impl<'lt, M, D> AsMut<[D]> for Mbuf<'lt, M, D> {
149    fn as_mut(&mut self) -> &mut [D] {
150        self
151    }
152}
153
154impl<'lt, M, D> std::ops::Deref for Mbuf<'lt, M, D> {
155    type Target = [D];
156
157    fn deref(&self) -> &Self::Target {
158        unsafe {
159            let address =
160                std::ptr::from_ref::<usize>(&self.length) as usize + std::mem::size_of::<usize>();
161
162            std::slice::from_raw_parts(align::<D>(address), self.length)
163        }
164    }
165}
166
167impl<'lt, M, D> std::ops::DerefMut for Mbuf<'lt, M, D> {
168    fn deref_mut(&mut self) -> &mut Self::Target {
169        unsafe {
170            let address =
171                std::ptr::from_ref::<usize>(&self.length) as usize + std::mem::size_of::<usize>();
172
173            std::slice::from_raw_parts_mut(align::<D>(address).cast_mut(), self.length)
174        }
175    }
176}
177
178const fn align<T>(address: usize) -> *const T {
179    let align_size = std::mem::align_of::<T>();
180    let remainder = address % align_size;
181
182    if remainder == 0 {
183        address as *const T
184    } else {
185        (address + align_size - remainder) as *const T
186    }
187}