everything_plugin/data/
mod.rs1use std::{
17 ffi::{CStr, CString, c_void},
18 fmt::Debug,
19 mem::MaybeUninit,
20 path::PathBuf,
21};
22
23use serde::{Serialize, de::DeserializeOwned};
24use tracing::{debug, error};
25
26use crate::{PluginApp, PluginHandler, PluginHost, sys};
27
28pub mod config;
29
30pub trait Config: Serialize + DeserializeOwned + Send + Debug + 'static {}
31
32impl<T: Serialize + DeserializeOwned + Send + Debug + 'static> Config for T {}
33
34impl<A: PluginApp> PluginHandler<A> {
35 pub fn load_settings(&self, data: *mut c_void) -> Option<A::Config> {
36 match self.get_host() {
37 Some(host) => {
38 let s = host.plugin_get_setting_string(data, "_", 0 as _);
39 if !s.is_null() {
40 let config = unsafe { CStr::from_ptr(s as _) };
41 debug!(
42 config = %config.to_str().unwrap_or("Invalid UTF-8"),
43 "Plugin config",
44 );
45 match serde_json::from_slice(config.to_bytes()) {
46 Ok(config) => Some(config),
47 Err(e) => {
48 error!(%e, "Plugin config parse error");
49 None
50 }
51 }
52 } else {
53 None
54 }
55 }
56 None if !data.is_null() => {
57 let config = *unsafe { Box::from_raw(data as *mut A::Config) };
59 debug!(?config, "Plugin config");
60 Some(config)
61 }
62 None => None,
63 }
64 }
65
66 pub fn save_settings(&self, data: *mut c_void) -> *mut c_void {
67 let config = unsafe { self.app() }.config();
68 let config = serde_json::to_string(config).unwrap();
69 debug!(%config, "Plugin save settings");
70
71 self.host().plugin_set_setting_string(data, "_", &config);
72 1 as _
73 }
74}
75
76impl PluginHost {
77 fn os_get_app_data_path_cat_filename_common(&self, name: &str, filename: &str) -> PathBuf {
78 let os_get_app_data_path_cat_filename: unsafe extern "system" fn(
79 filename: *const sys::everything_plugin_utf8_t,
80 cbuf: *mut sys::everything_plugin_utf8_buf_t,
81 ) = unsafe { self.get(name).unwrap_unchecked() };
82
83 let filename = CString::new(filename).unwrap();
84
85 let mut cbuf = MaybeUninit::uninit();
86 self.utf8_buf_init(cbuf.as_mut_ptr());
87
88 unsafe { os_get_app_data_path_cat_filename(filename.as_ptr() as _, cbuf.as_mut_ptr()) };
89
90 self.utf8_buf_into_string(cbuf.as_mut_ptr()).into()
91 }
92
93 pub fn os_get_app_data_path(&self) -> PathBuf {
94 self.os_get_app_data_path_cat_filename("")
95 }
96
97 pub fn os_get_app_data_path_cat_filename(&self, filename: &str) -> PathBuf {
106 self.os_get_app_data_path_cat_filename_common("os_get_app_data_path_cat_filename", filename)
107 }
108
109 pub fn os_get_local_app_data_path(&self) -> PathBuf {
110 self.os_get_local_app_data_path_cat_filename("")
111 }
112
113 pub fn os_get_local_app_data_path_cat_filename(&self, filename: &str) -> PathBuf {
119 self.os_get_app_data_path_cat_filename_common(
120 "os_get_local_app_data_path_cat_filename",
121 filename,
122 )
123 }
124
125 pub fn plugin_get_setting_string(
134 &self,
135 data: *mut c_void,
136 name: &str,
137 current_string: *mut sys::everything_plugin_utf8_t,
138 ) -> *mut sys::everything_plugin_utf8_t {
139 let plugin_get_setting_string: unsafe extern "system" fn(
141 sorted_list: *mut c_void,
142 name: *const sys::everything_plugin_utf8_t,
143 current_string: *mut sys::everything_plugin_utf8_t,
144 ) -> *mut sys::everything_plugin_utf8_t =
145 unsafe { self.get("plugin_get_setting_string").unwrap_unchecked() };
146 let name = CString::new(name).unwrap();
147 unsafe { plugin_get_setting_string(data, name.as_ptr() as _, current_string) }
148 }
149
150 pub fn plugin_set_setting_string(&self, data: *mut c_void, name: &str, value: &str) {
163 debug_assert!(
164 !value.contains('\n'),
165 "setting string value must be single-line"
166 );
167
168 let plugin_set_setting_string: unsafe extern "system" fn(
170 output_stream: sys::everything_plugin_output_stream_t,
171 name: *const sys::everything_plugin_utf8_t,
172 value: *const sys::everything_plugin_utf8_t,
173 ) = unsafe { self.get("plugin_set_setting_string").unwrap_unchecked() };
174 let name = CString::new(name).unwrap();
175 let value = CString::new(value).unwrap();
176 unsafe { plugin_set_setting_string(data, name.as_ptr() as _, value.as_ptr() as _) };
177 }
178
179 pub fn plugin_setting_json_path(&self) -> PathBuf {
183 self.os_get_app_data_path().join("plugins.json")
184 }
185}