Skip to main content

fre_rs/
data.rs

1//! 
2//! This module provides safe conversions between concrete typed instances
3//! and raw pointers for native data.
4//! 
5//! [`Box<dyn Any>`] is a fat pointer stored on the stack. Casting it directly
6/// to a raw pointer will truncate its metadata. To preserve type information,
7/// the fat pointer must be stored intact on the heap, so it can be safely
8/// reconstructed from a raw pointer.
9/// 
10
11
12use super::*;
13
14
15pub(crate) type ExtensionData = Arc<Mutex<Box<dyn Any>>>;
16impl Data for ExtensionData {}
17
18
19/// Should be implemented for all native data types to ensure safe pointer passing
20/// and correct memory management. Native data includes Extension Data, Context Data,
21/// and Function data.
22/// 
23pub trait Data: 'static + Sized {
24    fn into_boxed (self) -> Box<dyn Any> {
25        super::data::into_boxed(self)
26    }
27    fn into_raw (self) -> NonNullFREData {
28        super::data::into_raw(self.into_boxed())
29    }
30    fn from_boxed (boxed: Box<dyn Any>) -> Result<Self, Box<dyn Any>> {
31        boxed.downcast()
32            .map(|b| *b)
33            .map_err(|b| b)
34    }
35    #[allow(unsafe_op_in_unsafe_fn)]
36    unsafe fn from_raw (raw: NonNullFREData) -> Self {
37        let boxed = super::data::from_raw(raw);
38        Self::from_boxed(boxed).unwrap()
39    }
40    #[allow(unsafe_op_in_unsafe_fn)]
41    unsafe fn ref_from <'a> (raw: NonNullFREData) -> Result<&'a Self, &'a dyn Any> {
42        let any = super::data::ref_from(raw);
43        any.downcast_ref().ok_or(any)
44    }
45    #[allow(unsafe_op_in_unsafe_fn)]
46    unsafe fn mut_from <'a> (raw: NonNullFREData) -> Result<&'a mut Self, &'a mut dyn Any> {
47        let fat = super::data::mut_from(raw) as *mut dyn Any;
48        (&mut (*fat)).downcast_mut().ok_or(&mut (*fat))
49    }
50}
51impl Data for () {}
52
53
54type DataPointer = *mut *mut (dyn Any + 'static);
55
56
57pub fn into_boxed <D: 'static> (data: D) -> Box<dyn Any> {
58    Box::new(data) as Box<dyn Any>
59}
60pub fn into_raw (boxed: Box<dyn Any>) -> NonNullFREData {
61    let fat = Box::into_raw(boxed);
62    let raw: DataPointer = Box::into_raw(Box::new(fat));
63    unsafe {NonNull::new_unchecked(raw as FREData)}
64}
65#[allow(unsafe_op_in_unsafe_fn)]
66pub unsafe fn from_raw (raw: NonNullFREData) -> Box<dyn Any> {
67    let raw = raw.as_ptr() as DataPointer;
68    let fat = Box::from_raw(raw);
69    let boxed = Box::from_raw(*fat);
70    boxed
71}
72#[allow(unsafe_op_in_unsafe_fn)]
73pub unsafe fn ref_from <'a> (raw: NonNullFREData) -> &'a dyn Any {
74    let raw = raw.as_ptr() as DataPointer;
75    let any = &(**raw);
76    any
77}
78#[allow(unsafe_op_in_unsafe_fn)]
79pub unsafe fn mut_from <'a> (raw: NonNullFREData) -> &'a mut dyn Any {
80    let raw = raw.as_ptr() as DataPointer;
81    let any = &mut (**raw);
82    any
83}
84#[allow(unsafe_op_in_unsafe_fn)]
85pub unsafe fn drop_from (raw: NonNullFREData) {
86    drop(from_raw(raw));
87}