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}