metacall/types/
metacall_pointer.rs1use super::MetaCallValue;
2use crate::{
3 bindings::{metacall_value_create_ptr, metacall_value_destroy, metacall_value_to_ptr},
4 MetaCallNull,
5};
6use std::{
7 ffi::c_void,
8 fmt::{self, Debug, Formatter},
9};
10
11pub struct MetaCallPointer {
14 leak: bool,
15 rust_value: *mut Box<dyn MetaCallValue>,
16 rust_value_leak: bool,
17 value: *mut c_void,
18}
19unsafe impl Send for MetaCallPointer {}
20unsafe impl Sync for MetaCallPointer {}
21impl Clone for MetaCallPointer {
22 fn clone(&self) -> Self {
23 Self {
24 leak: true,
25 rust_value: self.rust_value,
26 rust_value_leak: true,
27 value: self.value,
28 }
29 }
30}
31impl Debug for MetaCallPointer {
32 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
33 let boxed_value = unsafe { Box::from_raw(self.rust_value) };
34 let value = if (*boxed_value).is::<MetaCallNull>() {
35 None
36 } else {
37 Some(format!("{:#?}", boxed_value))
38 };
39 Box::leak(boxed_value);
40
41 f.debug_struct("MetaCallPointer")
42 .field("value", &value)
43 .finish()
44 }
45}
46
47impl MetaCallPointer {
48 fn get_rust_value_ptr(value: *mut c_void) -> *mut Box<dyn MetaCallValue> {
49 unsafe { metacall_value_to_ptr(value) as *mut Box<dyn MetaCallValue> }
50 }
51
52 #[doc(hidden)]
53 pub fn new_raw(value: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
54 Ok(Self {
55 leak: false,
56 rust_value: Self::get_rust_value_ptr(value),
57 rust_value_leak: false,
58 value,
59 })
60 }
61
62 #[doc(hidden)]
63 pub fn new_raw_leak(value: *mut c_void) -> Result<Self, Box<dyn MetaCallValue>> {
64 Ok(Self {
65 leak: true,
66 rust_value: Self::get_rust_value_ptr(value),
67 rust_value_leak: false,
68 value,
69 })
70 }
71
72 pub fn new(ptr: impl MetaCallValue) -> Self {
74 let rust_value = Box::into_raw(Box::new(Box::new(ptr) as Box<dyn MetaCallValue>));
75
76 Self {
77 leak: false,
78 rust_value,
79 rust_value_leak: false,
80 value: unsafe { metacall_value_create_ptr(rust_value.cast()) },
81 }
82 }
83
84 pub fn get_value_untyped(mut self) -> Box<dyn MetaCallValue> {
87 self.rust_value_leak = true;
88
89 unsafe { *Box::from_raw(self.rust_value) }
90 }
91 pub fn get_value<T: MetaCallValue>(self) -> Result<T, Box<dyn MetaCallValue>> {
93 match self.get_value_untyped().downcast::<T>() {
94 Ok(rust_value) => Ok(rust_value),
95 Err(original) => Err(original),
96 }
97 }
98
99 #[doc(hidden)]
100 pub fn into_raw(mut self) -> *mut c_void {
101 self.leak = true;
102 self.rust_value_leak = true;
103
104 self.value
105 }
106}
107
108impl Drop for MetaCallPointer {
109 fn drop(&mut self) {
110 if !self.leak {
111 unsafe { metacall_value_destroy(self.value) }
112 }
113
114 if !self.rust_value_leak {
115 unsafe { drop(Box::from_raw(self.rust_value)) }
116 }
117 }
118}