gravityfile_plugin/
types.rs

1//! Core types for the plugin system.
2
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7
8/// Result type for plugin operations.
9pub type PluginResult<T> = Result<T, PluginError>;
10
11/// Errors that can occur in the plugin system.
12#[derive(Debug, Error)]
13pub enum PluginError {
14    /// Plugin file not found.
15    #[error("Plugin not found: {path}")]
16    NotFound { path: PathBuf },
17
18    /// Failed to load plugin.
19    #[error("Failed to load plugin '{name}': {message}")]
20    LoadError { name: String, message: String },
21
22    /// Plugin execution error.
23    #[error("Plugin '{name}' execution error: {message}")]
24    ExecutionError { name: String, message: String },
25
26    /// Plugin was cancelled.
27    #[error("Plugin '{name}' was cancelled")]
28    Cancelled { name: String },
29
30    /// Plugin timed out.
31    #[error("Plugin '{name}' timed out after {timeout_ms}ms")]
32    Timeout { name: String, timeout_ms: u64 },
33
34    /// Invalid plugin configuration.
35    #[error("Invalid plugin configuration: {message}")]
36    ConfigError { message: String },
37
38    /// Permission denied.
39    #[error("Permission denied for plugin '{name}': {action}")]
40    PermissionDenied { name: String, action: String },
41
42    /// Runtime not available.
43    #[error("Runtime '{runtime}' is not available")]
44    RuntimeNotAvailable { runtime: String },
45
46    /// IO error.
47    #[error("IO error: {0}")]
48    Io(#[from] std::io::Error),
49
50    /// Serialization error.
51    #[error("Serialization error: {0}")]
52    Serialization(String),
53
54    /// Hook not implemented.
55    #[error("Hook '{hook}' not implemented by plugin '{name}'")]
56    HookNotImplemented { name: String, hook: String },
57}
58
59/// Categories of plugins.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
61#[serde(rename_all = "lowercase")]
62pub enum PluginKind {
63    #[default]
64    /// Custom analysis plugins (find patterns, compute metrics).
65    /// Runs asynchronously in the background.
66    Analyzer,
67
68    /// File preview generation plugins (syntax highlighting, thumbnails).
69    /// Runs in an isolated context for safety.
70    Previewer,
71
72    /// Custom file operation plugins (compress, archive, transform).
73    /// Runs asynchronously with progress reporting.
74    Action,
75
76    /// Custom column/cell rendering plugins (git status, permissions).
77    /// Runs synchronously on the main thread.
78    Renderer,
79
80    /// Search and filter plugins (custom search algorithms).
81    /// Can be sync or async depending on implementation.
82    Filter,
83
84    /// Event listener plugins (logging, notifications).
85    /// Runs synchronously as callbacks.
86    Hook,
87}
88
89impl std::fmt::Display for PluginKind {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        match self {
92            Self::Analyzer => write!(f, "analyzer"),
93            Self::Previewer => write!(f, "previewer"),
94            Self::Action => write!(f, "action"),
95            Self::Renderer => write!(f, "renderer"),
96            Self::Filter => write!(f, "filter"),
97            Self::Hook => write!(f, "hook"),
98        }
99    }
100}
101
102/// A dynamic value that can be passed between Rust and plugin runtimes.
103///
104/// This is a simplified representation that can be converted to/from
105/// runtime-specific value types (mlua::Value, rhai::Dynamic, etc.).
106#[derive(Debug, Clone, Serialize, Deserialize)]
107#[serde(untagged)]
108pub enum Value {
109    /// Null/nil value.
110    Null,
111
112    /// Boolean value.
113    Bool(bool),
114
115    /// Integer value.
116    Integer(i64),
117
118    /// Floating point value.
119    Float(f64),
120
121    /// String value.
122    String(String),
123
124    /// Array/list value.
125    Array(Vec<Value>),
126
127    /// Object/table/map value.
128    Object(std::collections::HashMap<String, Value>),
129
130    /// Binary data.
131    Bytes(Vec<u8>),
132}
133
134impl Value {
135    /// Create a null value.
136    pub fn null() -> Self {
137        Self::Null
138    }
139
140    /// Check if this value is null.
141    pub fn is_null(&self) -> bool {
142        matches!(self, Self::Null)
143    }
144
145    /// Try to get this value as a boolean.
146    pub fn as_bool(&self) -> Option<bool> {
147        match self {
148            Self::Bool(b) => Some(*b),
149            _ => None,
150        }
151    }
152
153    /// Try to get this value as an integer.
154    pub fn as_i64(&self) -> Option<i64> {
155        match self {
156            Self::Integer(i) => Some(*i),
157            _ => None,
158        }
159    }
160
161    /// Try to get this value as a float.
162    pub fn as_f64(&self) -> Option<f64> {
163        match self {
164            Self::Float(f) => Some(*f),
165            Self::Integer(i) => Some(*i as f64),
166            _ => None,
167        }
168    }
169
170    /// Try to get this value as a string.
171    pub fn as_str(&self) -> Option<&str> {
172        match self {
173            Self::String(s) => Some(s),
174            _ => None,
175        }
176    }
177
178    /// Try to get this value as an array.
179    pub fn as_array(&self) -> Option<&[Value]> {
180        match self {
181            Self::Array(arr) => Some(arr),
182            _ => None,
183        }
184    }
185
186    /// Try to get this value as an object.
187    pub fn as_object(&self) -> Option<&std::collections::HashMap<String, Value>> {
188        match self {
189            Self::Object(obj) => Some(obj),
190            _ => None,
191        }
192    }
193}
194
195impl Default for Value {
196    fn default() -> Self {
197        Self::Null
198    }
199}
200
201impl From<bool> for Value {
202    fn from(b: bool) -> Self {
203        Self::Bool(b)
204    }
205}
206
207impl From<i64> for Value {
208    fn from(i: i64) -> Self {
209        Self::Integer(i)
210    }
211}
212
213impl From<i32> for Value {
214    fn from(i: i32) -> Self {
215        Self::Integer(i as i64)
216    }
217}
218
219impl From<u64> for Value {
220    fn from(u: u64) -> Self {
221        Self::Integer(u as i64)
222    }
223}
224
225impl From<f64> for Value {
226    fn from(f: f64) -> Self {
227        Self::Float(f)
228    }
229}
230
231impl From<String> for Value {
232    fn from(s: String) -> Self {
233        Self::String(s)
234    }
235}
236
237impl From<&str> for Value {
238    fn from(s: &str) -> Self {
239        Self::String(s.to_string())
240    }
241}
242
243impl<T: Into<Value>> From<Vec<T>> for Value {
244    fn from(arr: Vec<T>) -> Self {
245        Self::Array(arr.into_iter().map(Into::into).collect())
246    }
247}
248
249impl From<std::collections::HashMap<String, Value>> for Value {
250    fn from(obj: std::collections::HashMap<String, Value>) -> Self {
251        Self::Object(obj)
252    }
253}
254
255impl From<PathBuf> for Value {
256    fn from(path: PathBuf) -> Self {
257        Self::String(path.to_string_lossy().to_string())
258    }
259}