pawkit/
lib.rs

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}