1use std::alloc::{self, Layout};
8use std::mem;
9use std::ptr;
10
11pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
24 if size == 0 {
25 return ptr::null_mut();
26 }
27
28 let layout = Layout::from_size_align_unchecked(size, align);
29 alloc::alloc(layout)
30}
31
32pub unsafe fn deallocate(ptr: *mut u8, size: usize, align: usize) {
38 if !ptr.is_null() && size > 0 {
39 let layout = Layout::from_size_align_unchecked(size, align);
40 alloc::dealloc(ptr, layout);
41 }
42}
43
44pub unsafe fn fast_memcpy(dst: *mut u8, src: *const u8, count: usize) {
57 if count < 32 {
58 for i in 0..count {
59 *dst.add(i) = *src.add(i);
60 }
61 return;
62 }
63
64 let dst_ptr = dst as *mut usize;
65 let src_ptr = src as *const usize;
66 let word_size = mem::size_of::<usize>();
67 let word_count = count / word_size;
68
69 for i in 0..word_count {
70 *dst_ptr.add(i) = *src_ptr.add(i);
71 }
72
73 let remaining_offset = word_count * word_size;
74 for i in 0..(count - remaining_offset) {
75 *dst.add(remaining_offset + i) = *src.add(remaining_offset + i);
76 }
77}
78
79pub unsafe fn fast_memset(dst: *mut u8, value: u8, count: usize) {
91 if count < 32 {
92 for i in 0..count {
93 *dst.add(i) = value;
94 }
95 return;
96 }
97
98 *dst = value;
99
100 let mut i = 1;
101 while i <= count / 2 {
102 ptr::copy_nonoverlapping(dst, dst.add(i), i);
103 i *= 2;
104 }
105
106 if i < count {
107 ptr::copy_nonoverlapping(dst, dst.add(i), count - i);
108 }
109}
110
111pub unsafe fn secure_zero_memory(ptr: *mut u8, count: usize) {
123 for i in 0..count {
124 ptr::write_volatile(ptr.add(i), 0);
125 }
126 std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst);
127}
128
129pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, new_size: usize, align: usize) -> *mut u8 {
146 if ptr.is_null() {
147 return allocate(new_size, align);
148 }
149
150 if new_size == 0 {
151 deallocate(ptr, old_size, align);
152 return ptr::null_mut();
153 }
154
155 let old_layout = Layout::from_size_align_unchecked(old_size, align);
156 let new_layout = Layout::from_size_align_unchecked(new_size, align);
157
158 alloc::realloc(ptr, old_layout, new_size)
159}
160
161pub struct MemoryBlock {
162 ptr: *mut u8,
163 size: usize,
164 align: usize,
165}
166
167impl MemoryBlock {
168 pub fn new(size: usize, align: usize) -> Option<Self> {
169 unsafe {
170 let ptr = allocate(size, align);
171 if ptr.is_null() {
172 None
173 } else {
174 Some(Self { ptr, size, align })
175 }
176 }
177 }
178
179 pub fn as_ptr(&self) -> *mut u8 {
180 self.ptr
181 }
182
183 pub fn size(&self) -> usize {
184 self.size
185 }
186
187 pub fn fill(&mut self, value: u8) {
188 unsafe {
189 fast_memset(self.ptr, value, self.size);
190 }
191 }
192
193 pub fn resize(&mut self, new_size: usize) -> bool {
194 unsafe {
195 let new_ptr = reallocate(self.ptr, self.size, new_size, self.align);
196 if new_ptr.is_null() {
197 return false;
198 }
199 self.ptr = new_ptr;
200 self.size = new_size;
201 true
202 }
203 }
204
205 pub fn secure_zero(&mut self) {
206 unsafe {
207 secure_zero_memory(self.ptr, self.size);
208 }
209 }
210}
211
212impl Drop for MemoryBlock {
213 fn drop(&mut self) {
214 unsafe {
215 deallocate(self.ptr, self.size, self.align);
216 }
217 }
218}
219
220#[derive(Debug)]
221pub struct MemoryAccess<'a> {
222 ptr: *mut u8,
223 size: usize,
224 _phantom: std::marker::PhantomData<&'a mut [u8]>,
225}
226
227impl<'a> MemoryAccess<'a> {
228 pub unsafe fn new(ptr: *mut u8, size: usize) -> Self {
234 Self {
235 ptr,
236 size,
237 _phantom: std::marker::PhantomData,
238 }
239 }
240
241 pub fn read<T: Copy>(&self, offset: usize) -> T {
246 assert!(
247 offset + mem::size_of::<T>() <= self.size,
248 "Read out of bounds"
249 );
250 unsafe { ptr::read_unaligned(self.ptr.add(offset) as *const T) }
251 }
252
253 pub fn write<T>(&mut self, offset: usize, value: T) {
258 assert!(
259 offset + mem::size_of::<T>() <= self.size,
260 "Write out of bounds"
261 );
262 unsafe {
263 ptr::write_unaligned(self.ptr.add(offset) as *mut T, value);
264 }
265 }
266
267 pub fn slice(&self, offset: usize, len: usize) -> &[u8] {
272 assert!(offset + len <= self.size, "Slice out of bounds");
273 unsafe { std::slice::from_raw_parts(self.ptr.add(offset), len) }
274 }
275
276 pub fn slice_mut(&mut self, offset: usize, len: usize) -> &mut [u8] {
281 assert!(offset + len <= self.size, "Slice out of bounds");
282 unsafe { std::slice::from_raw_parts_mut(self.ptr.add(offset), len) }
283 }
284}