panda/plugins/guest_plugin_manager/
guest_plugin.rs1use std::{ffi::CString, io::Write, os::raw::c_char, path::Path, ptr};
2
3use super::GUEST_PLUGIN_MANAGER;
4
5pub type ChannelId = u32;
7
8pub type ChannelCB = extern "C" fn(ChannelId, *const u8, usize);
10
11#[repr(C)]
13pub struct GuestPlugin {
14 pub plugin_name: *const c_char,
15 pub guest_binary_path: *const c_char,
16 pub msg_receive_cb: ChannelCB,
17}
18
19#[repr(transparent)]
21pub struct Channel(ChannelId);
22
23impl Channel {
24 pub fn write_packet(&mut self, buf: &[u8]) {
26 GUEST_PLUGIN_MANAGER.channel_write(self.0, buf.as_ptr(), buf.len());
27 }
28
29 pub fn new(callback: ChannelCB) -> Self {
31 Channel(GUEST_PLUGIN_MANAGER.allocate_channel(callback))
32 }
33
34 pub fn id(&self) -> ChannelId {
36 self.0
37 }
38}
39
40impl Write for Channel {
41 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
42 self.write_packet(buf);
43
44 Ok(buf.len())
45 }
46
47 fn flush(&mut self) -> std::io::Result<()> {
48 Ok(())
49 }
50}
51
52pub fn load_guest_plugin(name: impl Into<String>, msg_received: ChannelCB) -> Channel {
58 Channel(GUEST_PLUGIN_MANAGER.add_guest_plugin(GuestPlugin::new(name.into(), msg_received)))
59}
60
61impl GuestPlugin {
62 pub fn new(plugin_name: String, msg_receive_cb: ChannelCB) -> Self {
65 let plugin_name = CString::new(plugin_name).unwrap().into_raw();
66
67 GuestPlugin {
68 plugin_name,
69 guest_binary_path: ptr::null(),
70 msg_receive_cb,
71 }
72 }
73
74 pub fn new_with_path(
77 plugin_name: String,
78 guest_binary_path: &Path,
79 msg_receive_cb: ChannelCB,
80 ) -> Self {
81 let plugin_name = CString::new(plugin_name).unwrap().into_raw();
82 let guest_binary_path = CString::new(guest_binary_path.to_string_lossy().into_owned())
83 .unwrap()
84 .into_raw();
85
86 GuestPlugin {
87 plugin_name,
88 guest_binary_path,
89 msg_receive_cb,
90 }
91 }
92}