use crate::*;
#[derive(Clone)]
#[repr(C)]
#[allow(missing_docs)]
pub struct CustomOps {
pub identifier: *const ocaml_sys::Char,
pub finalize: Option<unsafe extern "C" fn(v: Raw)>,
pub compare: Option<unsafe extern "C" fn(v1: Raw, v2: Raw) -> i32>,
pub hash: Option<unsafe extern "C" fn(v: Raw) -> Int>,
pub serialize: Option<unsafe extern "C" fn(v: Raw, bsize_32: *mut Uint, bsize_64: *mut Uint)>,
pub deserialize: Option<unsafe extern "C" fn(dst: *mut core::ffi::c_void) -> Uint>,
pub compare_ext: Option<unsafe extern "C" fn(v1: Raw, v2: Raw) -> i32>,
pub fixed_length: *const sys::custom_fixed_length,
}
impl Default for CustomOps {
fn default() -> CustomOps {
DEFAULT_CUSTOM_OPS
}
}
pub trait Custom: Sized {
const NAME: &'static str;
const FIXED_LENGTH: Option<sys::custom_fixed_length> = None;
const OPS: CustomOps;
const USED: usize = 0;
const MAX: usize = 1;
unsafe extern "C" fn finalize(v: Raw) {
let p = v.as_pointer::<Self>();
p.drop_in_place();
}
fn ops() -> &'static CustomOps {
&Self::OPS
}
}
#[macro_export]
macro_rules! custom {
($name:ident $(<$($t:tt),*>)? $({$($k:ident : $v:expr),* $(,)? })?) => {
impl $(<$($t),*>)? $crate::Custom for $name $(<$($t),*>)? {
$crate::custom! {
name: concat!("rust.", stringify!($name))
$(, $($k: $v),*)?
}
}
};
{name : $name:expr $(, fixed_length: $fl:expr)? $(, $($k:ident : $v:expr),*)? $(,)? } => {
const NAME: &'static str = concat!($name, "\0");
const OPS: $crate::custom::CustomOps = $crate::custom::CustomOps {
identifier: Self::NAME.as_ptr() as *const $crate::sys::Char,
$($($k: Some($v),)*)?
..$crate::custom::CustomOps {
finalize: Some(Self::finalize),
.. $crate::custom::DEFAULT_CUSTOM_OPS
}
};
};
}
unsafe impl<T: Custom> FromValue for &T {
fn from_value(v: Value) -> Self {
let ptr = Pointer::from_value(v);
unsafe { &*ptr.as_ptr() }
}
}
unsafe impl<T: Custom> FromValue for &mut T {
fn from_value(v: Value) -> Self {
let mut ptr = Pointer::from_value(v);
unsafe { &mut *ptr.as_mut_ptr() }
}
}
#[macro_export]
macro_rules! custom_finalize {
($name:ident $(<$t:tt>)?, $f:path) => {
$crate::custom!($name { finalize: $f });
};
}
pub const DEFAULT_CUSTOM_OPS: CustomOps = CustomOps {
identifier: core::ptr::null(),
fixed_length: core::ptr::null_mut(),
compare: None,
compare_ext: None,
deserialize: None,
finalize: None,
hash: None,
serialize: None,
};