2022-10-14 14:53:30 +00:00
|
|
|
/// The foreign function interfaces for the dynamic data
|
2022-10-14 08:33:19 +00:00
|
|
|
mod dynamic_data;
|
2022-10-14 14:53:30 +00:00
|
|
|
/// The foreign function interfaces for that static data
|
2022-09-18 16:02:13 +00:00
|
|
|
mod static_data;
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Helper type for clearer functions.
|
2022-09-18 16:02:13 +00:00
|
|
|
type OwnedPtr<T> = *mut T;
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Helper type for clearer functions.
|
2022-09-18 16:02:13 +00:00
|
|
|
type BorrowedPtr<T> = *const T;
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Generates a basic getter foreign function interface.
|
2022-10-08 11:15:04 +00:00
|
|
|
macro_rules! ffi_arc_getter {
|
|
|
|
(
|
|
|
|
$type:ty, $func:ident, $returns: ty
|
|
|
|
) => {
|
|
|
|
paste::paste! {
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer<Arc<$type>>) -> $returns {
|
|
|
|
ptr.as_ref().$func()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-01-03 12:56:20 +00:00
|
|
|
/// Generates a basic getter foreign function interface.
|
|
|
|
macro_rules! ffi_arc_dyn_getter {
|
|
|
|
(
|
|
|
|
$type:ty, $func:ident, $returns: ty
|
|
|
|
) => {
|
|
|
|
paste::paste! {
|
|
|
|
#[no_mangle]
|
|
|
|
extern "C" fn [< $type:snake _ $func >](ptr: ExternPointer<Arc<dyn $type>>) -> $returns {
|
|
|
|
ptr.as_ref().$func()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Generates a basic getter foreign function interface where the return type is a [`crate::StringKey`].
|
2022-10-08 11:15:04 +00:00
|
|
|
macro_rules! ffi_arc_stringkey_getter {
|
2022-09-18 16:02:13 +00:00
|
|
|
(
|
|
|
|
$type:ty, $func:ident
|
|
|
|
) => {
|
|
|
|
paste::paste! {
|
|
|
|
#[no_mangle]
|
2023-01-03 12:56:20 +00:00
|
|
|
extern "C" fn [< $type:lower _ $func >](ptr: ExternPointer<Arc<dyn $type>>) -> OwnedPtr<c_char> {
|
2022-09-18 16:02:13 +00:00
|
|
|
std::ffi::CString::new(ptr.as_ref().$func().str()).unwrap().into_raw()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Generates a foreign function interface for a vec. This generates a length function, and a getter.
|
2022-09-18 16:02:13 +00:00
|
|
|
macro_rules! ffi_vec_value_getters {
|
|
|
|
(
|
2023-01-03 12:56:20 +00:00
|
|
|
$name:ident, $type:ty, $func:ident, $returns: ty
|
2022-09-18 16:02:13 +00:00
|
|
|
) => {
|
|
|
|
paste::paste! {
|
|
|
|
#[no_mangle]
|
2023-01-03 12:56:20 +00:00
|
|
|
extern "C" fn [< $name:lower _ $func _length>](ptr: ExternPointer<Arc<$type>>) -> usize {
|
2022-09-18 16:02:13 +00:00
|
|
|
ptr.as_ref().$func().len()
|
|
|
|
}
|
|
|
|
#[no_mangle]
|
2023-01-03 12:56:20 +00:00
|
|
|
extern "C" fn [< $name:lower _ $func _get>](ptr: ExternPointer<Arc<$type>>, index: usize) -> $returns {
|
2022-09-18 16:02:13 +00:00
|
|
|
*ptr.as_ref().$func().get(index).unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Generates a foreign function interface for a vec of [`crate::StringKey`]. This generates a
|
|
|
|
/// length function, and a getter.
|
2022-09-18 16:02:13 +00:00
|
|
|
macro_rules! ffi_vec_stringkey_getters {
|
|
|
|
(
|
2022-11-28 20:34:28 +00:00
|
|
|
$type:ty, $func:ident
|
2022-09-18 16:02:13 +00:00
|
|
|
) => {
|
|
|
|
paste::paste! {
|
|
|
|
#[no_mangle]
|
2023-01-03 12:56:20 +00:00
|
|
|
extern "C" fn [< $type:lower _ $func _length>](ptr: ExternPointer<Arc<dyn $type>>) -> usize {
|
2022-09-18 16:02:13 +00:00
|
|
|
ptr.as_ref().$func().len()
|
|
|
|
}
|
|
|
|
#[no_mangle]
|
2023-01-03 12:56:20 +00:00
|
|
|
extern "C" fn [< $type:lower _ $func _get>](ptr: ExternPointer<Arc<dyn $type>>, index: usize) -> OwnedPtr<c_char> {
|
2022-09-18 16:02:13 +00:00
|
|
|
CString::new(ptr.as_ref().$func().get(index).unwrap().str()).unwrap().into_raw()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-08 11:15:04 +00:00
|
|
|
use crate::{ValueIdentifiable, ValueIdentifier};
|
2023-01-03 12:56:20 +00:00
|
|
|
pub(self) use ffi_arc_dyn_getter;
|
2022-10-08 11:15:04 +00:00
|
|
|
pub(self) use ffi_arc_getter;
|
|
|
|
pub(self) use ffi_arc_stringkey_getter;
|
2022-09-18 16:02:13 +00:00
|
|
|
pub(self) use ffi_vec_stringkey_getters;
|
|
|
|
pub(self) use ffi_vec_value_getters;
|
2023-04-15 12:34:42 +00:00
|
|
|
use std::ffi::{c_char, CString};
|
2022-10-14 14:53:30 +00:00
|
|
|
use std::mem::transmute;
|
2022-10-08 11:15:04 +00:00
|
|
|
use std::sync::Arc;
|
2022-09-18 16:02:13 +00:00
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Helper utility class to wrap a pointer for extern functions.
|
2022-09-18 16:02:13 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub(self) struct ExternPointer<T: ?Sized> {
|
2022-10-14 14:53:30 +00:00
|
|
|
/// The wrapped pointer.
|
2022-09-18 16:02:13 +00:00
|
|
|
ptr: *mut T,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ?Sized> ExternPointer<T> {
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Get the internal pointer as reference.
|
2023-04-16 17:57:21 +00:00
|
|
|
#[allow(clippy::panic)] // We currently allow this as these should never be null, but we might want to change this in the future.
|
2022-09-18 16:02:13 +00:00
|
|
|
pub(self) fn as_ref(&self) -> &T {
|
|
|
|
unsafe {
|
2022-10-14 14:53:30 +00:00
|
|
|
self.ptr
|
|
|
|
.as_ref()
|
|
|
|
.unwrap_or_else(|| panic!("Given pointer of type '{}' was null", std::any::type_name::<T>()))
|
2022-09-18 16:02:13 +00:00
|
|
|
}
|
|
|
|
}
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Get the internal pointer as mutable reference.
|
2023-04-16 17:57:21 +00:00
|
|
|
#[allow(clippy::panic)] // We currently allow this as these should never be null, but we might want to change this in the future.
|
2022-10-14 14:53:30 +00:00
|
|
|
pub(self) fn as_mut(&mut self) -> &mut T {
|
2022-09-18 16:02:13 +00:00
|
|
|
unsafe {
|
2022-10-14 14:53:30 +00:00
|
|
|
self.ptr
|
|
|
|
.as_mut()
|
|
|
|
.unwrap_or_else(|| panic!("Given pointer of type '{}' was null", std::any::type_name::<T>()))
|
2022-09-18 16:02:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Helper utility class to give both the pointer and identifier to a FFI.
|
2022-10-08 11:15:04 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub(self) struct IdentifiablePointer<T> {
|
2022-10-14 14:53:30 +00:00
|
|
|
/// The wrapped pointer.
|
2022-10-08 11:15:04 +00:00
|
|
|
pub ptr: *const T,
|
2022-10-14 14:53:30 +00:00
|
|
|
/// The identifier of the pointer.
|
|
|
|
pub id: usize,
|
2022-10-08 11:15:04 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 12:34:42 +00:00
|
|
|
impl<T> Clone for IdentifiablePointer<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
id: self.id,
|
|
|
|
ptr: self.ptr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Copy for IdentifiablePointer<T> {}
|
|
|
|
|
2022-10-14 08:33:19 +00:00
|
|
|
impl<T> IdentifiablePointer<T> {
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Creates a new IdentifiablePointer.
|
2022-10-14 08:33:19 +00:00
|
|
|
pub(self) fn new(ptr: *const T, id: ValueIdentifier) -> Self {
|
2022-10-14 14:53:30 +00:00
|
|
|
unsafe { Self { ptr, id: transmute(id) } }
|
2022-10-14 08:33:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:53:30 +00:00
|
|
|
impl<T> From<*mut T> for ExternPointer<T> {
|
|
|
|
fn from(ptr: *mut T) -> Self {
|
|
|
|
ExternPointer { ptr }
|
2022-10-14 11:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-27 16:29:29 +00:00
|
|
|
impl<T: ValueIdentifiable + ?Sized> From<Arc<T>> for IdentifiablePointer<Arc<T>> {
|
2022-10-08 11:15:04 +00:00
|
|
|
fn from(v: Arc<T>) -> Self {
|
2022-11-27 16:29:29 +00:00
|
|
|
let id = v.value_identifier().value();
|
2022-10-08 11:15:04 +00:00
|
|
|
Self {
|
|
|
|
ptr: Box::into_raw(Box::new(v)),
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-27 17:22:57 +00:00
|
|
|
impl<T: ValueIdentifiable + ?Sized> From<Option<Arc<T>>> for IdentifiablePointer<Arc<T>> {
|
2022-11-26 10:25:56 +00:00
|
|
|
fn from(v: Option<Arc<T>>) -> Self {
|
|
|
|
if let Some(v) = v {
|
|
|
|
let id = unsafe { transmute(v.value_identifier()) };
|
|
|
|
Self {
|
|
|
|
ptr: Box::into_raw(Box::new(v)),
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IdentifiablePointer::none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-27 17:22:57 +00:00
|
|
|
impl<T: ValueIdentifiable + ?Sized> From<Box<T>> for IdentifiablePointer<Box<T>> {
|
|
|
|
fn from(v: Box<T>) -> Self {
|
|
|
|
let id = unsafe { transmute(v.value_identifier()) };
|
|
|
|
Self {
|
|
|
|
ptr: Box::into_raw(Box::new(v)),
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-24 11:00:50 +00:00
|
|
|
impl<T: ValueIdentifiable + ?Sized> From<&Box<T>> for IdentifiablePointer<Box<T>> {
|
|
|
|
fn from(v: &Box<T>) -> Self {
|
|
|
|
let id = unsafe { transmute(v.value_identifier()) };
|
|
|
|
Self {
|
|
|
|
ptr: v as *const Box<T>,
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-27 17:22:57 +00:00
|
|
|
impl<T: ValueIdentifiable + ?Sized> From<Option<Box<T>>> for IdentifiablePointer<Box<T>> {
|
|
|
|
fn from(v: Option<Box<T>>) -> Self {
|
|
|
|
if let Some(v) = v {
|
|
|
|
let id = unsafe { transmute(v.value_identifier()) };
|
|
|
|
Self {
|
|
|
|
ptr: Box::into_raw(Box::new(v)),
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IdentifiablePointer::none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ValueIdentifiable + ?Sized> From<&Option<Box<T>>> for IdentifiablePointer<Box<T>> {
|
|
|
|
fn from(v: &Option<Box<T>>) -> Self {
|
|
|
|
if let Some(v) = v {
|
|
|
|
let id = unsafe { transmute(v.value_identifier()) };
|
|
|
|
unsafe {
|
|
|
|
Self {
|
|
|
|
ptr: *Box::into_raw(Box::new(v as *const Box<T>)),
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IdentifiablePointer::none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-08 11:15:04 +00:00
|
|
|
impl<T: ValueIdentifiable> From<Box<T>> for IdentifiablePointer<T> {
|
|
|
|
fn from(v: Box<T>) -> Self {
|
2022-10-14 14:53:30 +00:00
|
|
|
let id = unsafe { transmute(v.value_identifier()) };
|
2022-10-08 11:15:04 +00:00
|
|
|
Self {
|
|
|
|
ptr: Box::into_raw(v),
|
|
|
|
id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ValueIdentifiable> From<*const T> for IdentifiablePointer<T> {
|
2023-04-16 17:57:21 +00:00
|
|
|
#[allow(clippy::unwrap_used)] // We currently allow this as these should never be null, but we might want to change this in the future.
|
2022-10-08 11:15:04 +00:00
|
|
|
fn from(v: *const T) -> Self {
|
2022-10-14 14:53:30 +00:00
|
|
|
let id = unsafe { transmute(v.as_ref().unwrap().value_identifier()) };
|
2022-10-08 11:15:04 +00:00
|
|
|
Self { ptr: v, id }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IdentifiablePointer<T> {
|
2022-10-14 14:53:30 +00:00
|
|
|
/// Returns an identifiable pointer with null as pointer, and 0 as identifier.
|
2022-10-08 11:15:04 +00:00
|
|
|
pub fn none() -> Self {
|
|
|
|
Self {
|
|
|
|
ptr: std::ptr::null(),
|
|
|
|
id: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-15 12:34:42 +00:00
|
|
|
|
|
|
|
/// Helper utility class to give either the data or an error to a FFI.
|
|
|
|
#[repr(C)]
|
|
|
|
union ResultUnion<T: Copy> {
|
|
|
|
/// If the result is ok, this contains the value.
|
|
|
|
ok: T,
|
|
|
|
/// If the result is an error, this contains the error message.
|
|
|
|
err: OwnedPtr<c_char>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The result of a FFI call that can either be an error or a value.
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct NativeResult<T: Copy> {
|
|
|
|
/// If the result is ok, this is 1, otherwise 0.
|
|
|
|
ok: u8,
|
|
|
|
/// The value or error.
|
|
|
|
value: ResultUnion<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy> NativeResult<T> {
|
|
|
|
/// Creates a new NativeResult with the given value.
|
|
|
|
pub fn ok(value: T) -> Self {
|
|
|
|
Self {
|
|
|
|
ok: 1,
|
|
|
|
value: ResultUnion { ok: value },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Creates a new NativeResult with the given error.
|
2023-04-16 17:57:21 +00:00
|
|
|
#[allow(clippy::unwrap_used)] // We know for certain this is not empty.
|
|
|
|
pub fn err(err: anyhow_ext::Error) -> Self {
|
2023-04-15 12:34:42 +00:00
|
|
|
Self {
|
|
|
|
ok: 0,
|
|
|
|
value: ResultUnion {
|
|
|
|
err: CString::new(err.to_string()).unwrap().into_raw(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2023-04-16 17:57:21 +00:00
|
|
|
|
|
|
|
/// Creates a new NativeResult with the given error string.
|
|
|
|
#[allow(clippy::unwrap_used)] // We know for certain this is not empty.
|
|
|
|
pub fn err_from_str(err: &str) -> Self {
|
|
|
|
Self {
|
|
|
|
ok: 0,
|
|
|
|
value: ResultUnion {
|
|
|
|
err: CString::new(err).unwrap().into_raw(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2023-04-15 12:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy> From<anyhow::Result<T>> for NativeResult<T> {
|
|
|
|
fn from(value: anyhow::Result<T>) -> Self {
|
|
|
|
match value {
|
|
|
|
Ok(v) => Self::ok(v),
|
|
|
|
Err(e) => Self::err(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Copy> From<T> for NativeResult<T> {
|
|
|
|
fn from(value: T) -> Self {
|
|
|
|
Self::ok(value)
|
|
|
|
}
|
|
|
|
}
|