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}