• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kolja / zap / 16630800218

30 Jul 2025 06:32PM UTC coverage: 22.195%. Remained the same
16630800218

push

github

kolja
will still work if no plugins directory is present

0 of 1 new or added line in 1 file covered. (0.0%)

91 of 410 relevant lines covered (22.2%)

0.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/plugins.rs
1
use libloading::{Library, Symbol};
2
use std::fs;
3
use std::path::Path;
4
use tera;
5

6
use crate::errors::PluginLoadError;
7

8
type PluginRegisterFn = unsafe extern "C" fn(tera: &mut tera::Tera);
9
const PLUGIN_ENTRY_POINT: &[u8] = b"register_tera_custom_functions";
10

11
pub struct Plugins {
12
    libs: Vec<Library>,
13
}
14

15
impl Default for Plugins {
16
    fn default() -> Self {
×
17
        Self::new()
×
18
    }
19
}
20

21
impl Plugins {
22
    pub fn new() -> Self {
×
23
        Plugins { libs: Vec::new() }
×
24
    }
25

26
    pub fn load_plugin(
×
27
        &mut self,
28
        tera: &mut tera::Tera,
29
        plugin_path: &Path,
30
    ) -> Result<(), PluginLoadError> {
31
        unsafe {
32
            let lib = Library::new(plugin_path).map_err(|e| PluginLoadError::LibraryLoad {
×
33
                path: plugin_path.to_path_buf(),
×
34
                source: e,
×
35
            })?;
36

37
            self.libs.push(lib);
×
38
            let lib_ref = self.libs.last().unwrap(); // Safe as we just pushed
×
39

40
            // For error reporting, convert the entry point name to a String
41
            let entry_point_name_str = String::from_utf8_lossy(PLUGIN_ENTRY_POINT).into_owned();
×
42

43
            let register_fn: Symbol<PluginRegisterFn> =
×
44
                lib_ref.get(PLUGIN_ENTRY_POINT).map_err(|e| {
45
                    PluginLoadError::EntryPointNotFound {
×
46
                        plugin_path: plugin_path.to_path_buf(),
×
47
                        entry_point_name: entry_point_name_str,
×
48
                        source: e,
×
49
                    }
50
                })?;
51

52
            register_fn(tera);
×
53
        }
54
        Ok(())
×
55
    }
56

57
    pub fn load_plugins_from_dir(
×
58
        &mut self,
59
        tera: &mut tera::Tera,
60
        dir_path: &Path,
61
    ) -> Result<(), PluginLoadError> {
62

63
        // If the plugins directory doesn't exist, just return OK without loading any plugins
64
        if !dir_path.is_dir() {
×
NEW
65
            return Ok(());
×
66
        }
67

68
        for entry in fs::read_dir(dir_path).map_err(|e| PluginLoadError::DirectoryRead {
×
69
            path: dir_path.to_path_buf(),
×
70
            source: e,
×
71
        })? {
72
            let entry = entry.map_err(|e| PluginLoadError::DirectoryRead {
×
73
                path: dir_path.to_path_buf(),
×
74
                source: e,
×
75
            })?;
76
            let path = entry.path();
×
77

78
            let ext = path.extension().and_then(std::ffi::OsStr::to_str);
×
79
            if !matches!(ext, Some("so") | Some("dylib") | Some("dll")) {
×
80
                continue;
81
            }
82

83
            self.load_plugin(tera, &path).map_err(|e| {
×
84
                eprintln!("Warning: Failed to load plugin {path:?}: {e}");
×
85
                e
×
86
            })?;
87
        }
88
        Ok(())
×
89
    }
90
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc