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