pawkit/
lib.rs

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}