1#![feature(decl_macro, generic_atomic)]
2
3use std::{
4 alloc::{Layout, alloc, dealloc},
5 ffi::c_char,
6 ptr,
7};
8
9pub(crate) mod fs;
10pub(crate) mod input;
11pub(crate) mod logger;
12pub(crate) mod net;
13pub(crate) mod string;
14
15macro c_enum {
16 (
17 $ty:ident : $base_ty:ty {
18 $($rest:tt),* $(,)?
19 }
20 ) => {
21 type $ty = $base_ty;
22 c_enum!(@impl $base_ty, 0, $($rest),*);
23 },
24
25 (
26 $ty:ident {
27 $($rest:tt),* $(,)?
28 }
29 ) => {
30 type $ty = i32;
31 c_enum!(@impl i32, 0, $($rest),*);
32 },
33
34 (@impl $base_ty:ty, $_idx:expr,) => {},
35
36 (@impl $base_ty:ty, $_idx:expr,
37 $name:ident = $val:literal, $($rest:tt),*
38 ) => {
39 const $name: $base_ty = $val;
40 c_enum!(@impl $base_ty, ($val + 1), $($rest),*);
41 },
42
43 (@impl $base_ty:ty, $idx:expr,
44 $name:ident, $($rest:tt),*
45 ) => {
46 const $name: $base_ty = $idx;
47 c_enum!(@impl $base_ty, ($idx + 1), $($rest),*);
48 },
49
50 (@impl $base_ty:ty, $_idx:expr,
51 $name:ident = $val:literal
52 ) => {
53 const $name: $base_ty = $val;
54 },
55
56 (@impl $base_ty:ty, $idx:expr,
57 $name:ident
58 ) => {
59 const $name: $base_ty = $idx;
60 },
61}
62
63unsafe fn move_to_heap<T>(value: T) -> *mut T {
64 return Box::into_raw(Box::new(value));
65}
66
67unsafe fn drop_from_heap<T>(ptr: *mut T) {
68 unsafe {
69 if !ptr.is_aligned() || ptr.is_null() {
70 return;
71 }
72
73 drop(Box::from_raw(ptr));
74 }
75}
76
77unsafe fn move_to_stack<T>(ptr: *mut T) -> Option<T> {
78 unsafe {
79 if !ptr.is_aligned() || ptr.is_null() {
80 return None;
81 }
82
83 return Some(*Box::from_raw(ptr));
84 }
85}
86
87unsafe fn ptr_to_slice_mut<'a, T>(ptr: *mut T, size: usize) -> Option<&'a mut [T]> {
88 unsafe {
89 if size == 0 {
90 return Some(&mut []);
91 }
92
93 if !ptr.is_aligned() || ptr.is_null() {
94 return None;
95 }
96
97 return Some(std::slice::from_raw_parts_mut(ptr, size));
98 }
99}
100
101unsafe fn ptr_to_slice<'a, T>(ptr: *const T, size: usize) -> Option<&'a [T]> {
102 unsafe {
103 if size == 0 {
104 return Some(&[]);
105 }
106
107 if !ptr.is_aligned() || ptr.is_null() {
108 return None;
109 }
110
111 return Some(std::slice::from_raw_parts(ptr, size));
112 }
113}
114
115unsafe fn ptr_to_ref_mut<'a, T>(ptr: *mut T) -> Option<&'a mut T> {
116 unsafe {
117 if !ptr.is_aligned() || ptr.is_null() {
118 return None;
119 }
120
121 return Some(&mut *ptr);
122 }
123}
124
125unsafe fn ptr_to_ref<'a, T>(ptr: *const T) -> Option<&'a T> {
126 unsafe {
127 if !ptr.is_aligned() || ptr.is_null() {
128 return None;
129 }
130
131 return Some(&*ptr);
132 }
133}
134
135unsafe fn move_slice_to_heap<T: Copy>(slice: &[T], size: &mut usize) -> *mut T {
136 *size = slice.len();
137
138 unsafe {
139 let layout = Layout::array::<T>(slice.len()).unwrap();
140
141 let ptr = alloc(layout) as *mut T;
142
143 if ptr.is_null() {
144 std::alloc::handle_alloc_error(layout);
145 }
146
147 ptr::copy_nonoverlapping(slice.as_ptr(), ptr, slice.len());
148
149 return ptr;
150 }
151}
152
153unsafe fn drop_slice_from_heap<T>(ptr: *mut T, size: usize) {
154 if ptr.is_null() || size == 0 {
155 return;
156 }
157
158 let layout = Layout::array::<T>(size).unwrap();
159
160 unsafe {
161 dealloc(ptr as *mut u8, layout);
162 }
163}
164
165unsafe fn set_if_valid<T>(ptr: *mut T, value: T) {
166 unsafe {
167 let Some(ptr) = ptr_to_ref_mut(ptr) else {
168 return;
169 };
170
171 *ptr = value;
172 }
173}
174
175#[unsafe(no_mangle)]
176unsafe extern "C" fn pawkit_free_array(slice: *mut u8, size: usize) {
177 unsafe {
178 drop_slice_from_heap(slice, size);
179 }
180}
181
182#[unsafe(no_mangle)]
183unsafe extern "C" fn pawkit_free_string(str: *const c_char, size: usize) {
184 unsafe {
185 drop_slice_from_heap(str as *mut u8, size);
186 }
187}
188
189unsafe fn cstr_to_str<'a>(cstr: *const c_char, len: usize) -> Option<&'a str> {
190 if cstr.is_null() {
191 return None;
192 }
193
194 let bytes = unsafe { ptr_to_slice(cstr as *const u8, len)? };
195
196 return std::str::from_utf8(bytes).ok();
197}
198
199unsafe fn str_to_cstr<'a>(s: &'a str, len: &mut usize) -> *const c_char {
200 *len = s.len();
201 return s.as_ptr() as *const c_char;
202}
203
204unsafe fn disown_str_to_cstr(s: &str, len: &mut usize) -> *const c_char {
205 unsafe {
206 return move_slice_to_heap(s.as_bytes(), len) as *const c_char;
207 }
208}