use libloading::Library;
use safer_ffi::{derive_ReprC, layout::ReprC};
pub trait FAsProxy<'l> {
type FSelf;
}
impl<T: ReprC> FAsProxy<'_> for &T {
type FSelf = Self;
}
impl<T: ReprC> FAsProxy<'_> for &mut T {
type FSelf = Self;
}
macro_rules! impl_f_as_proxy {
($T:ty) => {
impl FAsProxy<'_> for $T {
type FSelf = Self;
}
};
}
pub trait FProxyFrom<'l, T> {
fn proxy_from(value: T, lib: &'l Library) -> Self;
}
pub trait FLocal { }
pub trait FReprC: ReprC + FLocal { }
impl<T: ReprC + FLocal> FReprC for T { }
macro_rules! impl_f_local {
($T:ty) => {
impl FLocal for $T { }
};
}
impl<T: FLocal> FLocal for *const T { }
impl<T: FLocal> FLocal for *mut T { }
impl<T: FLocal> FLocal for &T { }
impl<T: FLocal> FLocal for &mut T { }
macro_rules! impl_primitive {
($T:ty) => {
impl_f_as_proxy!($T);
impl_f_local!($T);
};
}
impl_primitive!(());
impl_primitive!(usize);
pub trait FToC {
type CType: FReprC;
fn to_c(self) -> Self::CType;
}
impl<T> FToC for T
where
T: FReprC
{
type CType = Self;
fn to_c(self) -> Self::CType {
self
}
}
#[macro_export]
macro_rules! impl_f_to_c {
($T:ty) => {
crate::impl_f_to_c!(impl crate, $T);
};
(impl $crat:tt, $T:ty) => {
impl $crat::FToC for $T {
type CType = *const ();
fn to_c(self) -> Self::CType {
Box::into_raw(Box::new(self)) as *const ()
}
}
impl $crat::FToC for &$T {
type CType = *const ();
fn to_c(self) -> Self::CType {
self as *const $T as *const ()
}
}
impl $crat::FToC for &mut $T {
type CType = *const ();
fn to_c(self) -> Self::CType {
self as *mut $T as *mut () as *const ()
}
}
};
}
pub trait FFromC: FToC {
unsafe fn from_c(c_type: Self::CType) -> Self;
}
#[macro_export]
macro_rules! impl_f_from_c {
($T:ty) => {
crate::impl_f_from_c!(impl crate, $T);
};
(impl $crat:tt, $T:ty) => {
impl $crat::FFromC for $T {
unsafe fn from_c(c_type: Self::CType) -> Self {
*Box::from_raw(c_type as *mut $T)
}
}
impl $crat::FFromC for &$T {
unsafe fn from_c(c_type: Self::CType) -> Self {
&*(c_type as *const $T)
}
}
impl $crat::FFromC for &mut $T {
unsafe fn from_c(c_type: Self::CType) -> Self {
&mut *(c_type as *const $T as *mut $T)
}
}
};
}
impl<T> FFromC for T
where
T: FToC + From<T::CType>,
{
unsafe fn from_c(c_type: Self::CType) -> Self {
Self::from(c_type)
}
}
impl<T> FProxyFrom<'_, T::CType> for T
where
T: FToC + From<T::CType>
{
fn proxy_from(value: T::CType, _: &'_ Library) -> Self {
Self::from(value)
}
}
#[derive_ReprC]
#[repr(C)]
pub struct U128 {
l: u64,
r: u64,
}
impl FLocal for U128 { }
impl From<u128> for U128 {
fn from(value: u128) -> Self {
let r = value & 0x0000_0000_0000_0000_FFFF_FFFF_FFFF_FFFF;
U128 {
l: ((value - r) >> 64) as u64,
r: r as u64,
}
}
}
impl From<U128> for u128 {
fn from(value: U128) -> Self {
((value.l as u128) << 64) + value.r as u128
}
}
impl FToC for u128 {
type CType = U128;
fn to_c(self) -> Self::CType {
From::from(self)
}
}
impl FAsProxy<'_> for u128 {
type FSelf = Self;
}
impl FAsProxy<'_> for U128 {
type FSelf = u128;
}
#[cfg(test)]
pub mod proxy {
use super::U128;
#[test]
fn test_u128() {
let u = 123u128;
println!("{u}");
let u2 = U128::from(u);
println!("l: {}, r: {}", u2.l, u2.r);
assert!(u == u128::from(u2));
}
}