dlauncher/extension/
mod.rs1#![doc = include_str!("../../EXTENSIONS.md")]
2
3use std::sync::Arc;
4
5use libloading::{Library, Symbol};
6use log::debug;
7
8use crate::{
9 extension::{config::ExtensionConfig, query::Query},
10 launcher::{util::config::Config, window::Window},
11};
12
13pub mod config;
14pub mod query;
15pub mod response;
16
17pub type ExtensionOutputFunc = unsafe extern "C" fn(ExtensionContext) -> ExtensionExitCode;
19
20pub enum ExtensionExitCode {
22 Ok,
24 Error(&'static str),
31}
32
33#[derive(Debug, Clone)]
34pub struct Extension {
35 pub library: Arc<Library>,
37 pub window: Window,
39 pub config: ExtensionConfig,
41 pub name: String,
43}
44
45#[derive(Debug, Clone)]
46pub struct ExtensionContext {
47 pub name: String,
51 pub window: Window,
53 pub input: Option<Query>,
55 pub config: ExtensionConfig,
57}
58
59impl Extension {
60 pub fn new(window: Window, config: Config, extension_name: String) -> Extension {
61 unsafe {
62 let filename = config.dir().join("extensions").join(&extension_name);
63 let library = Library::new(filename).unwrap();
64
65 Extension {
66 library: Arc::new(library),
67 window,
68 config: ExtensionConfig::new(&config, &extension_name),
69 name: extension_name,
70 }
71 }
72 }
73
74 pub fn on_input(&self, input: &str) -> ExtensionExitCode {
76 unsafe {
77 let output: Symbol<ExtensionOutputFunc> = self.library.get(b"on_input").unwrap();
78
79 output(ExtensionContext {
80 name: self.name.clone(),
81 input: Some(Query::from_str(input)),
82 window: self.window.clone(),
83 config: self.config.clone(),
84 })
85 }
86 }
87
88 pub fn on_init(&self) -> ExtensionExitCode {
90 unsafe {
91 if let Ok(output) = self.library.get::<ExtensionOutputFunc>(b"on_init") {
92 output(ExtensionContext {
93 name: self.name.clone(),
94 input: None,
95 window: self.window.clone(),
96 config: self.config.clone(),
97 })
98 } else {
99 debug!("Extension {} has no on_init function, skipped", self.name);
100 ExtensionExitCode::Ok
101 }
102 }
103 }
104
105 pub fn on_open(&self) -> ExtensionExitCode {
107 unsafe {
108 if let Ok(output) = self.library.get::<ExtensionOutputFunc>(b"on_open") {
109 output(ExtensionContext {
110 name: self.name.clone(),
111 input: None,
112 window: self.window.clone(),
113 config: self.config.clone(),
114 })
115 } else {
116 debug!("Extension {} has no on_open", self.name);
117 ExtensionExitCode::Ok
118 }
119 }
120 }
121}