1#![no_std]
21
22use core::{
23 error,
24 ffi::c_void,
25 fmt,
26 ops::{Deref, DerefMut},
27 ptr, result, slice,
28};
29
30pub type Result<T, E = Error> = result::Result<T, E>;
32
33#[derive(Debug)]
35pub enum Error {
36 Allocation,
37}
38
39impl fmt::Display for Error {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 Error::Allocation => write!(f, "memory allocation error"),
43 }
44 }
45}
46
47impl error::Error for Error {}
48
49pub struct VirtualMemory {
51 ptr: *mut c_void,
52 len: usize,
53}
54
55impl VirtualMemory {
56 pub fn new(len: usize) -> Result<Self> {
58 #[cfg(unix)]
59 {
60 let ptr = unsafe {
61 libc::mmap(
62 ptr::null_mut(),
63 len,
64 libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
65 libc::MAP_PRIVATE | libc::MAP_ANON,
66 -1,
67 0,
68 )
69 };
70
71 if ptr == libc::MAP_FAILED {
72 return Err(Error::Allocation);
73 }
74
75 Ok(Self { ptr, len })
76 }
77
78 #[cfg(windows)]
79 {
80 use windows_sys::Win32::System::Memory::{
81 VirtualAlloc, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE,
82 };
83
84 let ptr = unsafe {
85 VirtualAlloc(
86 ptr::null(),
87 len,
88 MEM_COMMIT | MEM_RESERVE,
89 PAGE_EXECUTE_READWRITE,
90 )
91 };
92
93 if ptr.is_null() {
94 return Err(Error::Allocation);
95 }
96
97 Ok(Self { ptr, len })
98 }
99 }
100
101 #[inline]
103 pub fn ptr(&self) -> *const u8 {
104 self.ptr as *const u8
105 }
106
107 #[inline]
109 pub fn mut_ptr(&mut self) -> *mut u8 {
110 self.ptr as *mut u8
111 }
112
113 #[inline]
115 #[allow(clippy::len_without_is_empty)]
116 pub fn len(&self) -> usize {
117 self.len
118 }
119}
120
121impl Deref for VirtualMemory {
123 type Target = [u8];
124
125 #[inline]
126 fn deref(&self) -> &Self::Target {
127 unsafe { slice::from_raw_parts(self.ptr as _, self.len) }
128 }
129}
130
131impl DerefMut for VirtualMemory {
133 #[inline]
134 fn deref_mut(&mut self) -> &mut Self::Target {
135 unsafe { slice::from_raw_parts_mut(self.ptr as _, self.len) }
136 }
137}
138
139impl Drop for VirtualMemory {
141 fn drop(&mut self) {
142 #[cfg(unix)]
143 unsafe {
144 libc::munmap(self.ptr, self.len);
145 }
146
147 #[cfg(windows)]
148 unsafe {
149 use windows_sys::Win32::System::Memory::{VirtualFree, MEM_RELEASE};
150
151 VirtualFree(self.ptr, 0, MEM_RELEASE);
152 }
153 }
154}