muzzman_lib/
module.rs

1use std::{fmt::Debug, path::Path, sync::Arc};
2
3use crate::prelude::*;
4use bytes_kman::TBytes;
5use libloading::{Library, Symbol};
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone)]
9pub enum ControlFlow {
10    Run,
11    Pause,
12    Break,
13}
14
15#[derive(
16    Default,
17    Debug,
18    Clone,
19    Copy,
20    Serialize,
21    Deserialize,
22    PartialEq,
23    Eq,
24    PartialOrd,
25    Ord,
26    Hash,
27    bytes_kman::Bytes,
28)]
29pub struct ModuleId(pub u64);
30
31impl From<MRef> for ModuleId {
32    fn from(value: MRef) -> Self {
33        value.read().unwrap().uid
34    }
35}
36
37#[derive(Serialize, Deserialize)]
38pub struct RefModule {
39    #[serde(skip)]
40    pub session: Option<Box<dyn TSession>>,
41    pub uid: ModuleId,
42}
43
44impl Debug for RefModule {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        f.debug_struct("ModuleInfo").finish()
47    }
48}
49
50impl PartialEq for RefModule {
51    fn eq(&self, other: &Self) -> bool {
52        self.uid == other.uid
53    }
54}
55
56#[derive(Clone)]
57pub struct Module {
58    pub name: String,
59    pub desc: String,
60    pub module: Box<dyn TModule>,
61    pub proxy: usize,
62    /// default module data/settings
63    pub settings: Data,
64    /// default element data/settings
65    pub element_data: Data,
66    pub info: MRef,
67}
68
69impl Debug for Module {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        f.debug_struct(&format!("Module {}", self.name))
72            .field("name", &self.name)
73            .field("desc", &self.desc)
74            .field("proxy", &self.proxy)
75            .field("settings", &self.settings)
76            .field("element_data", &self.element_data)
77            .finish()
78    }
79}
80
81pub trait TModule {
82    fn init(&self, info: MRef) -> Result<(), String>;
83
84    fn get_name(&self) -> String;
85    fn get_desc(&self) -> String;
86
87    fn init_settings(&self, data: &mut Data);
88    fn init_element_settings(&self, data: &mut Data);
89
90    fn init_element(&self, element_row: ERow);
91    fn step_element(
92        &self,
93        element_row: ERow,
94        control_flow: &mut ControlFlow,
95        storage: &mut Storage,
96    );
97
98    fn accept_extension(&self, filename: &str) -> bool;
99    fn accept_url(&self, url: String) -> bool;
100    fn accepted_protocols(&self) -> Vec<String>;
101
102    fn init_location(&self, location_ref: LRef, data: FileOrData);
103    fn step_location(
104        &self,
105        location_row: LRow,
106        control_flow: &mut ControlFlow,
107        storage: &mut Storage,
108    );
109
110    fn notify(&self, _ref: Ref, event: Event);
111
112    fn c(&self) -> Box<dyn TModule>;
113}
114
115impl Clone for Box<dyn TModule> {
116    fn clone(&self) -> Self {
117        self.c()
118    }
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize, bytes_kman::Bytes)]
122pub enum RawLibraryError {
123    NotFound,
124    DontHaveSymbolGetName,
125    DontHaveSymbolGetDesc,
126    DontHaveSymbolInit,
127    DontHaveSymbolInitSettings,
128    DontHaveSymbolInitElementSettings,
129    DontHaveSymbolInitElement,
130    DontHaveSymbolStepElement,
131    DontHaveSymbolAcceptExtension,
132    DontHaveSymbolAcceptUrl,
133    DontHaveSymbolAcceptedProtocols,
134    DontHaveSymbolInitLocation,
135    DontHaveSymbolStepLocation,
136    DontHaveSymbolNotify,
137}
138
139pub struct RawModule {
140    lib: &'static Library,
141
142    fn_init: Symbol<'static, fn(MRef) -> Result<(), String>>,
143
144    fn_get_name: Symbol<'static, fn() -> String>,
145    fn_get_desc: Symbol<'static, fn() -> String>,
146
147    fn_init_settings: Symbol<'static, fn(&mut Data)>,
148    fn_init_element_settings: Symbol<'static, fn(&mut Data)>,
149
150    fn_init_element: Symbol<'static, fn(ERow)>,
151    fn_init_location: Symbol<'static, fn(LRef, FileOrData)>,
152
153    fn_step_element: Symbol<'static, fn(ERow, &mut ControlFlow, &mut Storage)>,
154    fn_step_location: Symbol<'static, fn(LRow, &mut ControlFlow, &mut Storage)>,
155
156    fn_accept_extension: Symbol<'static, fn(&str) -> bool>,
157    fn_accept_url: Symbol<'static, fn(String) -> bool>,
158    fn_accepted_protocols: Symbol<'static, fn() -> Vec<String>>,
159
160    fn_notify: Symbol<'static, fn(Ref, Event)>,
161}
162
163impl RawModule {
164    pub fn new_module(path: &Path) -> Result<Box<dyn TModule>, RawLibraryError> {
165        match Self::new(path) {
166            Ok(module) => Ok(Box::new(Arc::new(module))),
167            Err(err) => Err(err),
168        }
169    }
170    pub fn new(path: &Path) -> Result<Self, RawLibraryError> {
171        let lib = unsafe { Library::new(path) };
172        if lib.is_err() {
173            return Err(RawLibraryError::NotFound);
174        }
175        let lib = Box::leak(Box::new(lib.unwrap()));
176
177        let fn_init = if let Ok(func) = unsafe { lib.get(b"init\0") } {
178            func
179        } else {
180            return Err(RawLibraryError::DontHaveSymbolInit);
181        };
182
183        let fn_get_name = if let Ok(func) = unsafe { lib.get(b"get_name\0") } {
184            func
185        } else {
186            return Err(RawLibraryError::DontHaveSymbolGetName);
187        };
188
189        let fn_get_desc = if let Ok(func) = unsafe { lib.get(b"get_desc\0") } {
190            func
191        } else {
192            return Err(RawLibraryError::DontHaveSymbolGetDesc);
193        };
194
195        let fn_init_settings = if let Ok(func) = unsafe { lib.get(b"init_settings\0") } {
196            func
197        } else {
198            return Err(RawLibraryError::DontHaveSymbolInitSettings);
199        };
200
201        let fn_init_element_settings =
202            if let Ok(func) = unsafe { lib.get(b"init_element_settings\0") } {
203                func
204            } else {
205                return Err(RawLibraryError::DontHaveSymbolInitElementSettings);
206            };
207
208        let fn_init_element = if let Ok(func) = unsafe { lib.get(b"init_element\0") } {
209            func
210        } else {
211            return Err(RawLibraryError::DontHaveSymbolInitElement);
212        };
213
214        let fn_step_element = if let Ok(func) = unsafe { lib.get(b"step_element\0") } {
215            func
216        } else {
217            return Err(RawLibraryError::DontHaveSymbolStepElement);
218        };
219
220        let fn_accept_extension = if let Ok(func) = unsafe { lib.get(b"accept_extension\0") } {
221            func
222        } else {
223            return Err(RawLibraryError::DontHaveSymbolAcceptExtension);
224        };
225
226        let fn_accept_url = if let Ok(func) = unsafe { lib.get(b"accept_url\0") } {
227            func
228        } else {
229            return Err(RawLibraryError::DontHaveSymbolAcceptUrl);
230        };
231
232        let fn_accepted_protocols = if let Ok(func) = unsafe { lib.get(b"accepted_protocols\0") } {
233            func
234        } else {
235            return Err(RawLibraryError::DontHaveSymbolAcceptedProtocols);
236        };
237
238        let fn_init_location = if let Ok(func) = unsafe { lib.get(b"init_location\0") } {
239            func
240        } else {
241            return Err(RawLibraryError::DontHaveSymbolInitLocation);
242        };
243
244        let fn_notify = if let Ok(func) = unsafe { lib.get(b"notify\0") } {
245            func
246        } else {
247            return Err(RawLibraryError::DontHaveSymbolNotify);
248        };
249
250        let fn_step_location = if let Ok(func) = unsafe { lib.get(b"step_location\0") } {
251            func
252        } else {
253            return Err(RawLibraryError::DontHaveSymbolStepLocation);
254        };
255
256        Ok(Self {
257            lib,
258            fn_init,
259            fn_get_name,
260            fn_get_desc,
261            fn_init_settings,
262            fn_init_element_settings,
263            fn_init_element,
264            fn_init_location,
265            fn_step_element,
266            fn_accept_extension,
267            fn_accept_url,
268            fn_accepted_protocols,
269            fn_notify,
270            fn_step_location,
271        })
272    }
273}
274
275impl Drop for RawModule {
276    fn drop(&mut self) {
277        let lib = unsafe { Box::from_raw((self.lib as *const _) as *mut Library) };
278        drop(lib)
279    }
280}
281
282impl TModule for Arc<RawModule> {
283    fn init(&self, info: MRef) -> Result<(), String> {
284        (*self.fn_init)(info)
285    }
286
287    fn get_name(&self) -> String {
288        (*self.fn_get_name)()
289    }
290
291    fn get_desc(&self) -> String {
292        (*self.fn_get_desc)()
293    }
294
295    fn init_settings(&self, data: &mut Data) {
296        (*self.fn_init_settings)(data)
297    }
298
299    fn init_element_settings(&self, data: &mut Data) {
300        (*self.fn_init_element_settings)(data)
301    }
302
303    fn init_element(&self, element: ERow) {
304        (*self.fn_init_element)(element)
305    }
306
307    fn step_element(&self, element: ERow, control_flow: &mut ControlFlow, storage: &mut Storage) {
308        (*self.fn_step_element)(element, control_flow, storage)
309    }
310
311    fn accept_extension(&self, filename: &str) -> bool {
312        (*self.fn_accept_extension)(filename)
313    }
314
315    fn accept_url(&self, url: String) -> bool {
316        (*self.fn_accept_url)(url)
317    }
318
319    fn accepted_protocols(&self) -> Vec<String> {
320        (*self.fn_accepted_protocols)()
321    }
322
323    fn init_location(&self, location: LRef, data: FileOrData) {
324        (*self.fn_init_location)(location, data)
325    }
326
327    fn notify(&self, info: Ref, event: Event) {
328        (*self.fn_notify)(info, event)
329    }
330
331    fn step_location(&self, location: LRow, control_flow: &mut ControlFlow, storage: &mut Storage) {
332        (*self.fn_step_location)(location, control_flow, storage)
333    }
334
335    fn c(&self) -> Box<dyn TModule> {
336        Box::new(self.clone())
337    }
338}
339
340pub trait TModuleInfo {
341    fn get_session(&self) -> Result<Box<dyn TSession>, SessionError>;
342
343    fn get_name(&self) -> Result<String, SessionError>;
344    fn set_name(&self, name: impl Into<String>) -> Result<(), SessionError>;
345    fn get_default_name(&self) -> Result<String, SessionError>;
346
347    fn get_desc(&self) -> Result<String, SessionError>;
348    fn set_desc(&self, desc: impl Into<String>) -> Result<(), SessionError>;
349    fn get_default_desc(&self) -> Result<String, SessionError>;
350
351    fn get_proxy(&self) -> Result<usize, SessionError>;
352    fn set_proxy(&self, proxy: usize) -> Result<(), SessionError>;
353
354    fn get_settings(&self) -> Result<Data, SessionError>;
355    fn set_settings(&self, settings: Data) -> Result<(), SessionError>;
356
357    fn get_element_settings(&self) -> Result<Data, SessionError>;
358    fn set_element_settings(&self, settings: Data) -> Result<(), SessionError>;
359
360    fn register_action(
361        &self,
362        name: String,
363        values: Vec<(String, Value)>,
364        callback: fn(MRef, values: Vec<Type>),
365    ) -> Result<(), SessionError>;
366    fn remove_action(&self, name: String) -> Result<(), SessionError>;
367    fn run_action(&self, name: String, data: Vec<Type>) -> Result<(), SessionError>;
368
369    fn step_element(
370        &self,
371        element_info: &ElementId,
372        control_flow: ControlFlow,
373        storage: Storage,
374    ) -> Result<(ControlFlow, Storage), SessionError>;
375    fn step_location(
376        &self,
377        location_info: &LocationId,
378        control_flow: ControlFlow,
379        storage: Storage,
380    ) -> Result<(ControlFlow, Storage), SessionError>;
381
382    fn accept_url(&self, url: String) -> Result<bool, SessionError>;
383    fn accept_extension(&self, filename: impl Into<String>) -> Result<bool, SessionError>;
384    fn accepted_protocols(&self) -> Result<Vec<String>, SessionError>;
385
386    fn init_element(&self, element_info: &ElementId) -> Result<(), SessionError>;
387    fn init_location(
388        &self,
389        location_info: &LocationId,
390        data: FileOrData,
391    ) -> Result<(), SessionError>;
392
393    fn notify(&self, info: ID, event: Event) -> Result<(), SessionError>;
394
395    fn id(&self) -> ModuleId;
396}
397
398impl TModuleInfo for MRef {
399    fn get_session(&self) -> Result<Box<dyn TSession>, SessionError> {
400        if let Some(session) = &self.read().unwrap().session {
401            return Ok(session.c());
402        }
403        Err(SessionError::InvalidSession)
404    }
405
406    fn get_name(&self) -> Result<String, SessionError> {
407        return self.get_session()?.module_get_name(&self.id());
408    }
409
410    fn set_name(&self, name: impl Into<String>) -> Result<(), SessionError> {
411        self.get_session()?.module_set_name(&self.id(), name.into())
412    }
413
414    fn get_default_name(&self) -> Result<String, SessionError> {
415        self.get_session()?.module_get_default_name(&self.id())
416    }
417
418    fn get_desc(&self) -> Result<String, SessionError> {
419        self.get_session()?.module_get_desc(&self.id())
420    }
421
422    fn set_desc(&self, desc: impl Into<String>) -> Result<(), SessionError> {
423        self.get_session()?.module_set_desc(&self.id(), desc.into())
424    }
425
426    fn get_default_desc(&self) -> Result<String, SessionError> {
427        self.get_session()?.module_get_default_desc(&self.id())
428    }
429
430    fn get_proxy(&self) -> Result<usize, SessionError> {
431        self.get_session()?.module_get_proxy(&self.id())
432    }
433
434    fn set_proxy(&self, proxy: usize) -> Result<(), SessionError> {
435        self.get_session()?.module_set_proxy(&self.id(), proxy)
436    }
437
438    fn get_settings(&self) -> Result<Data, SessionError> {
439        self.get_session()?.module_get_settings(&self.id())
440    }
441
442    fn set_settings(&self, settings: Data) -> Result<(), SessionError> {
443        self.get_session()?
444            .module_set_settings(&self.id(), settings)
445    }
446
447    fn get_element_settings(&self) -> Result<Data, SessionError> {
448        self.get_session()?.module_get_element_settings(&self.id())
449    }
450
451    fn set_element_settings(&self, settings: Data) -> Result<(), SessionError> {
452        self.get_session()?
453            .module_set_element_settings(&self.id(), settings)
454    }
455
456    fn register_action(
457        &self,
458        name: String,
459        values: Vec<(String, Value)>,
460        callback: fn(MRef, values: Vec<Type>),
461    ) -> Result<(), SessionError> {
462        self.get_session()?
463            .register_action(&self.id(), name, values, callback)
464    }
465
466    fn remove_action(&self, name: String) -> Result<(), SessionError> {
467        self.get_session()?.remove_action(&self.id(), name)
468    }
469
470    fn run_action(&self, name: String, data: Vec<Type>) -> Result<(), SessionError> {
471        self.get_session()?.run_action(&self.id(), name, data)
472    }
473
474    fn step_element(
475        &self,
476        element_info: &ElementId,
477        control_flow: ControlFlow,
478        storage: Storage,
479    ) -> Result<(ControlFlow, Storage), SessionError> {
480        self.get_session()?
481            .module_step_element(&self.id(), element_info, control_flow, storage)
482    }
483
484    fn step_location(
485        &self,
486        location_info: &LocationId,
487        control_flow: ControlFlow,
488        storage: Storage,
489    ) -> Result<(ControlFlow, Storage), SessionError> {
490        self.get_session()?
491            .module_step_location(&self.id(), location_info, control_flow, storage)
492    }
493
494    fn accept_url(&self, url: String) -> Result<bool, SessionError> {
495        self.get_session()?.module_accept_url(&self.id(), url)
496    }
497
498    fn accept_extension(&self, filename: impl Into<String>) -> Result<bool, SessionError> {
499        self.get_session()?
500            .module_accept_extension(&self.id(), &filename.into())
501    }
502
503    fn accepted_protocols(&self) -> Result<Vec<String>, SessionError> {
504        self.get_session()?.module_accepted_protocols(&self.id())
505    }
506
507    fn init_element(&self, element_info: &ElementId) -> Result<(), SessionError> {
508        self.get_session()?
509            .module_init_element(&self.id(), element_info)
510    }
511
512    fn init_location(
513        &self,
514        location_info: &LocationId,
515        data: FileOrData,
516    ) -> Result<(), SessionError> {
517        self.get_session()?
518            .module_init_location(&self.id(), location_info, data)
519    }
520
521    fn notify(&self, info: ID, event: Event) -> Result<(), SessionError> {
522        let session = self.get_session()?;
523        match info {
524            ID::Element(e) => session.element_notify(&e, event),
525            ID::Location(l) => session.location_notify(&l, event),
526        }
527    }
528
529    fn id(&self) -> ModuleId {
530        self.read().unwrap().uid
531    }
532}
533
534#[derive(Debug, Clone, Serialize, Deserialize, Hash, bytes_kman::Bytes)]
535pub struct ModuleInfo {
536    pub name: String,
537    pub desc: String,
538    // module hash
539    pub module: u64,
540    pub id: ModuleId,
541    pub proxy: usize,
542    pub settings: Data,
543    pub element_data: Data,
544}