1use std::fmt;
6
7use serde::{Deserialize, Serialize};
8
9pub trait ExtensionContext: Send + Sync {
11 fn extension_id(&self) -> &str;
13
14 fn version(&self) -> &str;
16
17 fn publisher(&self) -> &str;
19
20 fn display_name(&self) -> &str;
22
23 fn description(&self) -> &str;
25
26 fn is_development(&self) -> bool;
28}
29
30pub trait ExtensionMetadata: Send + Sync {
32 fn name(&self) -> &str;
34
35 fn publisher(&self) -> &str;
37
38 fn version(&self) -> &str;
40
41 fn description(&self) -> &str;
43
44 fn main(&self) -> &str;
46
47 fn activation_events(&self) -> &[String];
49
50 fn capabilities(&self) -> &[String];
52
53 fn dependencies(&self) -> &[String];
55
56 fn engine(&self) -> &str;
58}
59
60pub type GroveResult<T> = Result<T, GroveError>;
62
63#[derive(Debug, thiserror::Error)]
65pub enum GroveError {
66 #[error("Extension not found: {0}")]
68 ExtensionNotFound(String),
69
70 #[error("Extension activation failed: {0}")]
72 ActivationFailed(String),
73
74 #[error("Extension deactivation failed: {0}")]
76 DeactivationFailed(String),
77
78 #[error("Transport error: {0}")]
80 TransportError(String),
81
82 #[error("WASM runtime error: {0}")]
84 WASMError(String),
85
86 #[error("API error: {0}")]
88 APIError(String),
89
90 #[error("Configuration error: {0}")]
92 ConfigurationError(String),
93
94 #[error("I/O error: {0}")]
96 IoError(#[from] std::io::Error),
97
98 #[error("Serialization error: {0}")]
100 SerializationError(String),
101
102 #[error("Deserialization error: {0}")]
104 DeserializationError(String),
105
106 #[error("Operation timed out")]
108 Timeout,
109
110 #[error("Invalid argument: {0}")]
112 InvalidArgument(String),
113
114 #[error("Not implemented: {0}")]
116 NotImplemented(String),
117
118 #[error("{0}")]
120 Other(String),
121}
122
123
124pub trait Identifiable {
126 fn id(&self) -> &str;
128}
129
130pub trait Named {
132 fn name(&self) -> &str;
134}
135
136pub trait Configurable {
138 type Config;
140
141 fn configure(&mut self, config:Self::Config) -> anyhow::Result<()>;
143
144 fn config(&self) -> &Self::Config;
146}
147
148pub trait Resettable {
150 fn reset(&mut self) -> anyhow::Result<()>;
152}
153
154pub trait Disposable {
156 fn dispose(&mut self) -> anyhow::Result<()>;
158}
159
160pub trait ContextClone {
162 fn clone_with_context(&self, context:&serde_json::Value) -> anyhow::Result<Self>
164 where
165 Self: Sized;
166}
167
168pub trait Stateful {
170 type State: Clone;
172
173 fn state(&self) -> Self::State;
175
176 fn set_state(&mut self, state:Self::State) -> anyhow::Result<()>;
178
179 fn restore_state(&mut self, state:Self::State) -> anyhow::Result<()>;
181}
182
183pub trait Observable {
185 type Event;
187
188 fn subscribe(&self, callback:fn(Self::Event)) -> anyhow::Result<()>;
190
191 fn unsubscribe(&self) -> anyhow::Result<()>;
193}
194
195pub trait Validatable {
197 fn validate(&self) -> anyhow::Result<()>;
199}
200
201pub trait Serializable: Serialize + for<'de> Deserialize<'de> {
203 fn to_json(&self) -> anyhow::Result<String> {
205 serde_json::to_string(self).map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))
206 }
207
208 fn to_json_pretty(&self) -> anyhow::Result<String> {
210 serde_json::to_string_pretty(self).map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))
211 }
212
213 fn from_json(json:&str) -> anyhow::Result<Self>
215 where
216 Self: Sized, {
217 serde_json::from_str(json).map_err(|e| anyhow::anyhow!("Deserialization failed: {}", e))
218 }
219}
220
221impl<T> Serializable for T where T: Serialize + for<'de> Deserialize<'de> {}
223
224pub trait Versioned {
226 fn version(&self) -> &str;
228
229 fn is_compatible_with(&self, other_version:&str) -> bool;
231}
232
233pub trait Retryable {
235 fn execute_with_retry<F, T, E>(&self, mut operation:F, max_retries:u32, delay_ms:u64) -> anyhow::Result<T>
237 where
238 F: FnMut() -> Result<T, E> + Send,
239 E: std::fmt::Display + Send + 'static,
240 T: Send, {
241 let mut last_error = None;
242
243 for attempt in 0..=max_retries {
244 match operation() {
245 Ok(result) => return Ok(result),
246 Err(e) => {
247 last_error = Some(e.to_string());
248 if attempt < max_retries {
249 std::thread::sleep(std::time::Duration::from_millis(delay_ms));
250 }
251 },
252 }
253 }
254
255 Err(anyhow::anyhow!(
256 "Operation failed after {} attempts: {}",
257 max_retries + 1,
258 last_error.unwrap_or_else(|| "Unknown error".to_string())
259 ))
260 }
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 #[test]
268 fn test_grove_error_display() {
269 let err = GroveError::ExtensionNotFound("test.ext".to_string());
270 assert_eq!(err.to_string(), "Extension not found: test.ext");
271
272 let err = GroveError::Timeout;
273 assert_eq!(err.to_string(), "Operation timed out");
274 }
275
276 #[test]
277 fn test_serializable_trait() {
278 #[derive(Serialize, Deserialize, PartialEq, Debug)]
279 struct TestStruct {
280 value:i32,
281 }
282
283 let test = TestStruct { value:42 };
284 let json = test.to_json().unwrap();
285 let deserialized:TestStruct = TestStruct::from_json(&json).unwrap();
286 assert_eq!(test, deserialized);
287 }
288
289 #[test]
290 fn test_retryable_execute_with_retry() {
291 let retryable = RetryableTrait;
292
293 let mut attempt_count = 0;
294 let result = retryable.execute_with_retry(
295 || {
296 attempt_count += 1;
297 if attempt_count < 3 { Err("Not ready") } else { Ok("Success") }
298 },
299 5,
300 100,
301 );
302
303 assert!(result.is_ok());
304 assert_eq!(result.unwrap(), "Success");
305 assert_eq!(attempt_count, 3);
306 }
307}
308
309struct RetryableTrait;
311
312impl Retryable for RetryableTrait {}