1#![feature(decl_macro, generic_atomic)]
2
3use core::slice;
4use std::{
5 alloc::{Layout, alloc, dealloc},
6 ffi::c_char,
7 ptr,
8};
9
10mod fs;
11mod input;
12mod logger;
13mod net;
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 !ptr.is_aligned() || ptr.is_null() || size == 0 {
90 return None;
91 }
92
93 return Some(std::slice::from_raw_parts_mut(ptr, size));
94 }
95}
96
97unsafe fn ptr_to_slice<'a, T>(ptr: *const T, size: usize) -> Option<&'a [T]> {
98 unsafe {
99 if !ptr.is_aligned() || ptr.is_null() || size == 0 {
100 return None;
101 }
102
103 return Some(std::slice::from_raw_parts(ptr, size));
104 }
105}
106
107unsafe fn ptr_to_ref_mut<'a, T>(ptr: *mut T) -> Option<&'a mut T> {
108 unsafe {
109 if !ptr.is_aligned() || ptr.is_null() {
110 return None;
111 }
112
113 return Some(&mut *ptr);
114 }
115}
116
117unsafe fn ptr_to_ref<'a, T>(ptr: *const T) -> Option<&'a T> {
118 unsafe {
119 if !ptr.is_aligned() || ptr.is_null() {
120 return None;
121 }
122
123 return Some(&*ptr);
124 }
125}
126
127unsafe fn move_slice_to_heap<T: Copy>(slice: &[T], size: &mut usize) -> *mut T {
128 *size = slice.len();
129
130 unsafe {
131 let layout = Layout::array::<T>(slice.len()).unwrap();
132
133 let ptr = alloc(layout) as *mut T;
134
135 if ptr.is_null() {
136 std::alloc::handle_alloc_error(layout);
137 }
138
139 ptr::copy_nonoverlapping(slice.as_ptr(), ptr, slice.len());
140
141 return ptr;
142 }
143}
144
145unsafe fn drop_slice_from_heap<T>(ptr: *mut T, size: usize) {
146 if ptr.is_null() || size == 0 {
147 return;
148 }
149
150 let layout = Layout::array::<T>(size).unwrap();
151
152 unsafe {
153 dealloc(ptr as *mut u8, layout);
154 }
155}
156
157unsafe fn set_if_valid<T>(ptr: *mut T, value: T) {
158 unsafe {
159 let Some(ptr) = ptr_to_ref_mut(ptr) else {
160 return;
161 };
162
163 *ptr = value;
164 }
165}
166
167#[unsafe(no_mangle)]
168unsafe extern "C" fn pawkit_free_array(slice: *mut u8, size: usize) {
169 unsafe {
170 drop_slice_from_heap(slice, size);
171 }
172}
173
174#[unsafe(no_mangle)]
175unsafe extern "C" fn pawkit_free_string(str: *const c_char, size: usize) {
176 unsafe {
177 drop_slice_from_heap(str as *mut u8, size);
178 }
179}
180
181unsafe fn cstr_to_str<'a>(cstr: *const c_char, len: usize) -> Option<&'a str> {
182 if cstr.is_null() {
183 return None;
184 }
185
186 let bytes = unsafe { slice::from_raw_parts(cstr as *const u8, len) };
187
188 return std::str::from_utf8(bytes).ok();
189}
190
191unsafe fn str_to_cstr<'a>(s: &'a str, len: &mut usize) -> *const c_char {
192 *len = s.len();
193 return s.as_ptr() as *const c_char;
194}
195
196unsafe fn disown_str_to_cstr(s: &str, len: &mut usize) -> *const c_char {
197 unsafe {
198 return move_slice_to_heap(s.as_bytes(), len) as *const c_char;
199 }
200}