GitRoot

craft your forge, build your project, grow your community freely
 1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
 2//
 3// SPDX-License-Identifier: MIT
 4
 5use crate::{imports, Plugin, PluginReporter, PluginRun, Server};
 6use std::sync::{Arc, OnceLock};
 7
 8type DynServer = Arc<Server>;
 9type DynPlugin = Arc<dyn Plugin + Send + Sync>;
10type DynPluginReporter = Arc<dyn PluginReporter + Send + Sync>;
11
12static INSTANCE: OnceLock<DynServer> = OnceLock::new();
13static PLUGIN: OnceLock<DynPlugin> = OnceLock::new();
14static PLUGIN_REPORTER: OnceLock<DynPluginReporter> = OnceLock::new();
15
16pub fn register<T, F>(run: Vec<PluginRun>, plugin_factory: F)
17where
18    T: Plugin + Send + Sync,
19    F: FnOnce(DynServer) -> T,
20{
21    let _ = INSTANCE.set(Arc::new(Server::new(run)));
22    let static_server = INSTANCE.get().unwrap();
23    let _ = PLUGIN.set(Arc::new(plugin_factory(static_server.clone())));
24}
25
26pub fn register_reporter<T, F>(run: Vec<PluginRun>, plugin_factory: F)
27where
28    T: PluginReporter + Send + Sync,
29    F: FnOnce(DynServer) -> T,
30{
31    let _ = INSTANCE.set(Arc::new(Server::new(run)));
32    let static_server = INSTANCE.get().unwrap();
33    let _ = PLUGIN_REPORTER.set(Arc::new(plugin_factory(static_server.clone())));
34}
35
36pub fn get() -> DynServer {
37    INSTANCE
38        .get()
39        .expect("Server has not been initialized. Call Server::init() first.")
40        .clone()
41}
42
43pub fn with_plugin<F>(f: F)
44where
45    F: FnOnce(DynPlugin) -> Result<(), String>,
46{
47    if let Some(plugin) = PLUGIN.get() {
48        let _ =
49            f(plugin.clone()).map_err(|err| imports::log_error(String::from("unknown error"), err));
50    } else if let Some(plugin) = PLUGIN_REPORTER.get() {
51        let _ =
52            f(plugin.clone()).map_err(|err| imports::log_error(String::from("unknown error"), err));
53    } else {
54        imports::log_error(
55            String::from("Plugin not initialized after server was created"),
56            String::from("Fatal error"),
57        );
58    }
59}
60
61pub fn with_plugin_reporter<F>(f: F)
62where
63    F: FnOnce(DynPluginReporter) -> Result<(), String>,
64{
65    if let Some(plugin) = PLUGIN_REPORTER.get() {
66        let _ =
67            f(plugin.clone()).map_err(|err| imports::log_error(String::from("unknown error"), err));
68    } //no else the plugin is not a reporter
69}