Skip to main content

reovim_kernel/api/module/
error.rs

1//! Module error types.
2
3use std::fmt;
4
5use super::ModuleId;
6
7/// Errors that can occur during module operations.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum ModuleError {
10    /// Failed to load the shared object file.
11    LoadFailed(String),
12
13    /// Module does not export the required entry point.
14    NoEntryPoint(String),
15
16    /// Module initialization failed.
17    InitFailed(String),
18
19    /// Module API version is incompatible with kernel.
20    IncompatibleVersion {
21        /// Version the module requires.
22        module: (u32, u32),
23        /// Version the kernel provides.
24        kernel: (u32, u32),
25    },
26
27    /// Module is in use by another module.
28    InUse {
29        /// The module that cannot be unloaded.
30        module: ModuleId,
31        /// The module that depends on it.
32        by: ModuleId,
33    },
34
35    /// Module is not currently loaded.
36    NotLoaded(ModuleId),
37
38    /// Module file was not found.
39    NotFound(String),
40}
41
42// LLVM coverage artifact: match arm headers and closing braces in Display impl
43// are marked DA:0 despite all variants being exercised in tests.
44#[cfg_attr(coverage_nightly, coverage(off))]
45impl fmt::Display for ModuleError {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        match self {
48            Self::LoadFailed(msg) => write!(f, "failed to load module: {msg}"),
49            Self::NoEntryPoint(msg) => write!(f, "module missing entry point: {msg}"),
50            Self::InitFailed(msg) => write!(f, "module initialization failed: {msg}"),
51            Self::IncompatibleVersion { module, kernel } => {
52                write!(
53                    f,
54                    "module requires API {}.{}, kernel provides {}.{}",
55                    module.0, module.1, kernel.0, kernel.1
56                )
57            }
58            Self::InUse { module, by } => {
59                write!(f, "module '{module}' is in use by '{by}'")
60            }
61            Self::NotLoaded(id) => write!(f, "module '{id}' is not loaded"),
62            Self::NotFound(name) => write!(f, "module '{name}' not found"),
63        }
64    }
65}
66
67impl std::error::Error for ModuleError {}
68
69/// Result of module probe/initialization.
70///
71/// Linux equivalent: Return value from `probe()` function.
72/// - `Success` = success (Linux: `0`)
73/// - `Defer` = try again later (Linux: `-EPROBE_DEFER`)
74/// - `Failed` = permanent failure (Linux: negative errno)
75///
76/// # Example
77///
78/// ```ignore
79/// fn init(&mut self, ctx: &ModuleContext) -> ProbeResult {
80///     if !ctx.kernel.event_bus.has_subscriber("treesitter") {
81///         return ProbeResult::Defer("waiting for treesitter".into());
82///     }
83///     ProbeResult::Success
84/// }
85/// ```
86#[derive(Debug, Clone, PartialEq, Eq)]
87pub enum ProbeResult {
88    /// Probe succeeded, module is ready.
89    Success,
90    /// Probe deferred, retry later (with reason).
91    /// Linux equivalent: `-EPROBE_DEFER`
92    Defer(String),
93    /// Probe failed permanently.
94    Failed(ModuleError),
95}