rush_sync_server/commands/plugins.rs
1// =====================================================
2// FILE: commands/plugins.rs - OBJECT-SAFE PLUGIN SYSTEM
3// =====================================================
4
5use super::command::Command;
6use super::registry::CommandRegistry;
7
8/// ✅ PLUGIN SYSTEM für externe Commands - JETZT OBJECT-SAFE!
9pub trait CommandPlugin {
10 /// Lädt alle Commands des Plugins
11 fn load_commands(&self) -> Vec<Box<dyn Command>>;
12
13 /// Plugin Name
14 fn name(&self) -> &'static str;
15
16 /// Plugin Version (optional)
17 fn version(&self) -> &'static str {
18 "1.0.0"
19 }
20
21 /// Plugin ist verfügbar? (für conditional loading)
22 fn is_available(&self) -> bool {
23 true
24 }
25}
26
27/// Plugin Manager verwaltet alle Plugins
28pub struct PluginManager {
29 plugins: Vec<Box<dyn CommandPlugin>>,
30}
31
32impl PluginManager {
33 /// Neuer Plugin Manager
34 pub fn new() -> Self {
35 Self {
36 plugins: Vec::new(),
37 }
38 }
39
40 /// Plugin laden
41 pub fn load_plugin<T: CommandPlugin + 'static>(&mut self, plugin: T) -> &mut Self {
42 if plugin.is_available() {
43 log::debug!("Loading plugin: {} v{}", plugin.name(), plugin.version());
44 self.plugins.push(Box::new(plugin));
45 } else {
46 log::warn!("Plugin not available: {}", plugin.name());
47 }
48 self
49 }
50
51 /// Alle Plugin-Commands zur Registry hinzufügen
52 pub fn apply_to_registry(&mut self, registry: &mut CommandRegistry) {
53 for plugin in &self.plugins {
54 log::debug!("Applying plugin: {}", plugin.name());
55
56 for command in plugin.load_commands() {
57 registry.register_boxed(command);
58 }
59 }
60
61 // Registry nach Plugin-Loading neu initialisieren
62 registry.initialize();
63 }
64
65 /// Plugin-Statistiken
66 pub fn stats(&self) -> (usize, usize) {
67 let total = self.plugins.len();
68 let available = self.plugins.iter().filter(|p| p.is_available()).count();
69 (total, available)
70 }
71
72 /// Alle geladenen Plugins auflisten
73 pub fn list_plugins(&self) -> Vec<(&str, &str, bool)> {
74 self.plugins
75 .iter()
76 .map(|p| (p.name(), p.version(), p.is_available()))
77 .collect()
78 }
79}
80
81impl Default for PluginManager {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87// =====================================================
88// BEISPIEL-IMPLEMENTIERUNG - Network Plugin
89// =====================================================
90
91/*
92use crate::commands::command::Command;
93use crate::core::prelude::*;
94
95// Beispiel: Ping Command
96#[derive(Debug)]
97pub struct PingCommand;
98
99impl Command for PingCommand {
100 fn name(&self) -> &'static str { "ping" }
101 fn description(&self) -> &'static str { "Ping a host" }
102
103 fn matches(&self, command: &str) -> bool {
104 command.trim().to_lowercase().starts_with("ping")
105 }
106
107 fn execute_sync(&self, args: &[&str]) -> Result<String> {
108 match args.first() {
109 Some(host) => Ok(format!("Pinging {}...", host)),
110 None => Ok("Usage: ping <host>".to_string()),
111 }
112 }
113
114 fn priority(&self) -> u8 { 30 }
115}
116
117// Network Plugin
118pub struct NetworkPlugin;
119
120impl CommandPlugin for NetworkPlugin {
121 fn name(&self) -> &'static str {
122 "network"
123 }
124
125 fn version(&self) -> &'static str {
126 "1.0.0"
127 }
128
129 fn load_commands(&self) -> Vec<Box<dyn Command>> {
130 vec![
131 Box::new(PingCommand),
132 // Box::new(WgetCommand),
133 // Box::new(CurlCommand),
134 ]
135 }
136
137 fn is_available(&self) -> bool {
138 cfg!(feature = "network") // Nur mit network feature
139 }
140}
141
142// NUTZUNG:
143// let mut plugin_manager = PluginManager::new();
144// plugin_manager.load_plugin(NetworkPlugin);
145// plugin_manager.apply_to_registry(&mut registry);
146*/