Skip to main content

reovim_kernel/api/module/
id.rs

1//! Module identifier type.
2
3use std::{borrow::Cow, fmt};
4
5/// Unique identifier for a loadable module.
6///
7/// Convention: Use kebab-case names like "lang-rust", "feat-completion".
8///
9/// # Static vs Dynamic IDs
10///
11/// Module IDs can be either:
12/// - **Static** (`&'static str`): For compile-time known modules, use `ModuleId::new()`
13/// - **Dynamic** (`String`): For runtime-generated modules, use `ModuleId::from_string()`
14///
15/// Static IDs are preferred for performance (no allocation), but dynamic IDs
16/// allow for user-defined or plugin-loaded modules with arbitrary names.
17///
18/// # Example
19///
20/// ```
21/// use reovim_kernel::api::v1::ModuleId;
22///
23/// // Static ID (compile-time known)
24/// let static_id = ModuleId::new("lang-rust");
25///
26/// // Dynamic ID (runtime generated)
27/// let name = format!("user-plugin-{}", 42);
28/// let dynamic_id = ModuleId::from_string(name);
29///
30/// // Both work the same way
31/// assert_eq!(static_id.as_str(), "lang-rust");
32/// assert_eq!(dynamic_id.as_str(), "user-plugin-42");
33/// ```
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub struct ModuleId(Cow<'static, str>);
36
37impl ModuleId {
38    /// Create a new module identifier from a static string.
39    ///
40    /// This is the preferred way to create module IDs for statically-known modules.
41    /// It's a const fn and involves no allocation.
42    #[must_use]
43    pub const fn new(id: &'static str) -> Self {
44        Self(Cow::Borrowed(id))
45    }
46
47    /// Create a module identifier from an owned String.
48    ///
49    /// Use this for dynamically-generated module IDs (e.g., user plugins,
50    /// runtime-loaded modules with user-provided names).
51    #[must_use]
52    #[allow(clippy::missing_const_for_fn)] // String operations aren't const-stable
53    pub fn from_string(id: String) -> Self {
54        Self(Cow::Owned(id))
55    }
56
57    /// Get the identifier string.
58    #[must_use]
59    pub fn as_str(&self) -> &str {
60        &self.0
61    }
62
63    /// Check if this is a static (borrowed) ID.
64    #[must_use]
65    pub const fn is_static(&self) -> bool {
66        matches!(self.0, Cow::Borrowed(_))
67    }
68
69    /// Check if this is a dynamic (owned) ID.
70    #[must_use]
71    pub const fn is_dynamic(&self) -> bool {
72        matches!(self.0, Cow::Owned(_))
73    }
74}
75
76impl fmt::Display for ModuleId {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        write!(f, "{}", self.0)
79    }
80}
81
82impl From<&'static str> for ModuleId {
83    fn from(s: &'static str) -> Self {
84        Self::new(s)
85    }
86}
87
88impl From<String> for ModuleId {
89    fn from(s: String) -> Self {
90        Self::from_string(s)
91    }
92}