Skip to main content

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