pawkit/
lib.rs

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