Skip to main content

zsh/
modentry.rs

1//! Module entry point dispatch
2//!
3//! Port from zsh/Src/modentry.c (43 lines)
4//!
5//! In C, this is the dlopen entry point that dispatches setup/boot/cleanup/finish
6//! calls to loaded modules. In Rust, all modules are statically compiled,
7//! so this provides the ModuleLifecycle trait dispatch instead.
8
9use crate::module::ModuleLifecycle;
10
11/// Module entry operations (from modentry.c boot parameter)
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum ModOp {
14    Setup = 0,
15    Boot = 1,
16    Cleanup = 2,
17    Finish = 3,
18    Features = 4,
19    Enables = 5,
20}
21
22impl ModOp {
23    pub fn from_int(n: i32) -> Option<Self> {
24        match n {
25            0 => Some(ModOp::Setup),
26            1 => Some(ModOp::Boot),
27            2 => Some(ModOp::Cleanup),
28            3 => Some(ModOp::Finish),
29            4 => Some(ModOp::Features),
30            5 => Some(ModOp::Enables),
31            _ => None,
32        }
33    }
34}
35
36/// Dispatch a module lifecycle operation (from modentry.c modentry)
37pub fn modentry(op: ModOp, module: &mut dyn ModuleLifecycle) -> i32 {
38    match op {
39        ModOp::Setup => module.setup(),
40        ModOp::Boot => module.boot(),
41        ModOp::Cleanup => module.cleanup(),
42        ModOp::Finish => module.finish(),
43        ModOp::Features | ModOp::Enables => 0,
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50
51    struct TestModule {
52        booted: bool,
53    }
54    impl ModuleLifecycle for TestModule {
55        fn boot(&mut self) -> i32 {
56            self.booted = true;
57            0
58        }
59    }
60
61    #[test]
62    fn test_modentry_dispatch() {
63        let mut m = TestModule { booted: false };
64        assert_eq!(modentry(ModOp::Setup, &mut m), 0);
65        assert!(!m.booted);
66        assert_eq!(modentry(ModOp::Boot, &mut m), 0);
67        assert!(m.booted);
68    }
69
70    #[test]
71    fn test_modop_from_int() {
72        assert_eq!(ModOp::from_int(0), Some(ModOp::Setup));
73        assert_eq!(ModOp::from_int(1), Some(ModOp::Boot));
74        assert_eq!(ModOp::from_int(6), None);
75    }
76}