slowshell_plugin_abi/
payload.rs1use core::{ffi::c_void, fmt};
2
3use abi_stable::{
4 StableAbi, sabi_trait,
5 std_types::{RBox, ROption, RStr},
6};
7
8use crate::{Args, TypeKey};
9
10#[repr(C)]
11#[derive(StableAbi)]
12pub struct PayloadValue {
13 key: TypeKey,
14 ptr: *mut c_void,
15 clone_fn: extern "C" fn(*const c_void) -> *mut c_void,
16 drop_fn: extern "C" fn(*mut c_void),
17}
18
19unsafe impl Send for PayloadValue {}
20unsafe impl Sync for PayloadValue {}
21
22impl PayloadValue {
23 fn new<T: Clone + Send + Sync + 'static>(value: T) -> Self {
24 extern "C" fn clone_it<T: Clone + Send + Sync + 'static>(ptr: *const c_void) -> *mut c_void {
25 let value = unsafe { &*(ptr as *const T) };
26 Box::into_raw(Box::new(value.clone())) as *mut c_void
27 }
28
29 extern "C" fn drop_it<T>(ptr: *mut c_void) {
30 unsafe { drop(Box::from_raw(ptr as *mut T)) };
31 }
32
33 Self {
34 key: TypeKey::of::<T>(),
35 ptr: Box::into_raw(Box::new(value)) as *mut c_void,
36 clone_fn: clone_it::<T>,
37 drop_fn: drop_it::<T>,
38 }
39 }
40
41 fn clone_value(&self) -> Self {
42 Self {
43 key: self.key,
44 ptr: (self.clone_fn)(self.ptr as *const c_void),
45 clone_fn: self.clone_fn,
46 drop_fn: self.drop_fn,
47 }
48 }
49
50 fn is<T: 'static>(&self) -> bool {
51 self.key.matches::<T>()
52 }
53
54 fn as_ref<T: 'static>(&self) -> Option<&T> {
55 if self.is::<T>() {
56 Some(unsafe { &*(self.ptr as *const T) })
57 } else {
58 None
59 }
60 }
61
62 fn as_mut<T: 'static>(&mut self) -> Option<&mut T> {
63 if self.is::<T>() {
64 Some(unsafe { &mut *(self.ptr as *mut T) })
65 } else {
66 None
67 }
68 }
69}
70
71impl Clone for PayloadValue {
72 fn clone(&self) -> Self {
73 self.clone_value()
74 }
75}
76
77impl Drop for PayloadValue {
78 fn drop(&mut self) {
79 if !self.ptr.is_null() {
80 (self.drop_fn)(self.ptr);
81 self.ptr = core::ptr::null_mut();
82 }
83 }
84}
85
86#[repr(C)]
87#[derive(StableAbi)]
88pub struct PayloadBox {
89 value: PayloadValue,
90}
91
92impl PayloadBox {
93 pub fn new<T: Clone + Send + Sync + 'static>(value: T) -> Self {
94 Self {
95 value: PayloadValue::new(value),
96 }
97 }
98
99 pub fn is<T: 'static>(&self) -> bool {
100 self.value.is::<T>()
101 }
102
103 pub fn as_this<T: 'static>(&self) -> Option<&T> {
104 self.value.as_ref::<T>()
105 }
106
107 pub fn as_this_mut<T: 'static>(&mut self) -> Option<&mut T> {
108 self.value.as_mut::<T>()
109 }
110
111 pub fn type_key(&self) -> TypeKey {
112 self.value.key
113 }
114}
115
116impl Clone for PayloadBox {
117 fn clone(&self) -> Self {
118 Self {
119 value: self.value.clone_value(),
120 }
121 }
122}
123
124impl fmt::Debug for PayloadBox {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "PayloadBox<{}>", self.value.key.name)
127 }
128}
129
130#[sabi_trait]
131pub trait PayloadParser: Send + Sync + 'static {
132 fn parse(&self, command: RStr<'_>, args: &Args) -> ROption<PayloadBox>;
133}
134
135pub type PayloadParserBox = PayloadParser_TO<RBox<()>>;