atri_ffi/
lib.rs

1use std::mem::{ManuallyDrop, MaybeUninit};
2use std::ptr::null_mut;
3use std::{mem, slice};
4
5pub mod closure;
6pub mod contact;
7pub mod error;
8pub mod ffi;
9pub mod future;
10mod managed;
11pub mod message;
12pub mod plugin;
13pub use managed::*;
14
15pub type Handle = *const ();
16pub type PHandle = *const Handle;
17
18#[repr(C)]
19pub struct RustString {
20    pub ptr: *mut u8,
21    pub len: usize,
22    pub capacity: usize,
23}
24
25impl RustString {
26    pub fn null() -> Self {
27        Self {
28            ptr: null_mut(),
29            len: 0,
30            capacity: 0,
31        }
32    }
33
34    pub fn is_null(&self) -> bool {
35        self.ptr.is_null()
36    }
37}
38
39impl From<String> for RustString {
40    fn from(s: String) -> Self {
41        let mut ma = ManuallyDrop::new(s);
42        let ptr = ma.as_mut_ptr();
43        let len = ma.len();
44        let cap = ma.capacity();
45
46        Self {
47            ptr,
48            len,
49            capacity: cap,
50        }
51    }
52}
53
54impl From<RustString> for String {
55    fn from(s: RustString) -> Self {
56        let str = unsafe { String::from_raw_parts(s.ptr, s.len, s.capacity) };
57        str
58    }
59}
60
61impl AsRef<str> for RustString {
62    fn as_ref(&self) -> &str {
63        unsafe {
64            let slice = slice::from_raw_parts(self.ptr, self.len);
65            std::str::from_utf8_unchecked(slice)
66        }
67    }
68}
69
70impl ToString for RustString {
71    fn to_string(&self) -> String {
72        self.as_ref().to_string()
73    }
74}
75
76#[repr(C)]
77pub struct RustStr {
78    pub slice: *const u8,
79    pub len: usize,
80}
81
82impl RustStr {
83    pub fn as_str<'a>(&self) -> &'a str {
84        unsafe {
85            let slice = slice::from_raw_parts(self.slice, self.len);
86            std::str::from_utf8_unchecked(slice)
87        }
88    }
89}
90
91impl From<&str> for RustStr {
92    fn from(s: &str) -> Self {
93        Self {
94            slice: s.as_ptr(),
95            len: s.len(),
96        }
97    }
98}
99
100impl AsRef<str> for RustStr {
101    fn as_ref(&self) -> &str {
102        self.as_str()
103    }
104}
105
106impl ToString for RustStr {
107    fn to_string(&self) -> String {
108        self.as_ref().to_string()
109    }
110}
111
112#[repr(C)]
113pub struct RustVec<T: ?Sized> {
114    ptr: *mut T,
115    len: usize,
116    capacity: usize,
117}
118
119unsafe impl<T: Send> Send for RustVec<T> {}
120unsafe impl<T: Sync> Sync for RustVec<T> {}
121
122impl<T> RustVec<T> {
123    pub fn into_vec(self) -> Vec<T> {
124        unsafe { Vec::from_raw_parts(self.ptr, self.len, self.capacity) }
125    }
126}
127
128impl<T> From<Vec<T>> for RustVec<T> {
129    fn from(mut v: Vec<T>) -> Self {
130        let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
131        mem::forget(v);
132        Self {
133            ptr,
134            len,
135            capacity: cap,
136        }
137    }
138}
139
140#[repr(C)]
141pub struct RustSlice<T> {
142    ptr: *const T,
143    len: usize,
144}
145
146impl<T> RustSlice<T> {
147    pub fn as_ptr(&self) -> *const T {
148        self.ptr
149    }
150
151    pub fn as_slice(&self) -> &[T] {
152        unsafe { slice::from_raw_parts(self.ptr, self.len) }
153    }
154}
155
156impl<T> From<&[T]> for RustSlice<T> {
157    fn from(slice: &[T]) -> Self {
158        Self {
159            ptr: slice.as_ptr(),
160            len: slice.len(),
161        }
162    }
163}
164
165unsafe impl<T: Send> Send for RustSlice<T> {}
166unsafe impl<T: Sync> Sync for RustSlice<T> {}
167
168#[repr(C)]
169pub struct FFIOption<T> {
170    is_some: bool,
171    value: MaybeUninit<T>,
172}
173
174unsafe impl<T: Send> Send for FFIOption<T> {}
175unsafe impl<T: Sync> Sync for FFIOption<T> {}
176
177impl<T> From<Option<T>> for FFIOption<T> {
178    fn from(val: Option<T>) -> Self {
179        match val {
180            Some(t) => Self {
181                is_some: true,
182                value: MaybeUninit::new(t),
183            },
184            None => Self {
185                is_some: false,
186                value: MaybeUninit::uninit(),
187            },
188        }
189    }
190}
191
192impl<T> From<FFIOption<T>> for Option<T> {
193    fn from(ffi: FFIOption<T>) -> Self {
194        if ffi.is_some {
195            unsafe { Some(ffi.value.assume_init()) }
196        } else {
197            None
198        }
199    }
200}
201
202#[cfg(test)]
203mod tests {
204    use crate::{Managed, RustStr, RustString, RustVec};
205
206    #[test]
207    fn vec() {
208        let v = vec![1, 1, 4, 5, 1, 4];
209        let raw = RustVec::from(v);
210        let v = raw.into_vec();
211
212        assert_eq!(v, [1, 1, 4, 5, 1, 4]);
213    }
214
215    #[test]
216    fn string() {
217        let s = String::from("114514");
218        let raw = RustString::from(s);
219        let s = String::from(raw);
220
221        assert_eq!(s, "114514");
222
223        let slice = &s[1..];
224        let raw = RustStr::from(slice);
225        let slice = raw.as_ref();
226
227        assert_eq!(slice, "14514");
228    }
229
230    #[test]
231    fn managed_value() {
232        #[derive(Debug, Clone)]
233        struct Test {
234            a: i32,
235            b: usize,
236            c: Option<Box<(Test, Test)>>,
237        }
238
239        impl PartialEq for Test {
240            fn eq(&self, other: &Self) -> bool {
241                if self.a != other.a {
242                    return false;
243                }
244                if self.b != other.b {
245                    return false;
246                }
247
248                self.c == other.c
249            }
250        }
251
252        let test = Test {
253            a: 233,
254            b: 114514,
255            c: Some(Box::new((
256                Test {
257                    a: 23114,
258                    b: 114514,
259                    c: None,
260                },
261                Test {
262                    a: 114514,
263                    b: 2333,
264                    c: None,
265                },
266            ))),
267        };
268        let test0 = test.clone();
269        let managed = Managed::from_value(test);
270        let test: Test = unsafe { managed.into_value() };
271
272        assert_eq!(test, test0);
273    }
274}