trustformers_core/plugins/
info.rs1use crate::errors::{Result, TrustformersError};
4use semver::{Version, VersionReq};
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct PluginInfo {
32 name: String,
34 version: Version,
36 description: String,
38 author: Option<String>,
40 homepage: Option<String>,
42 license: Option<String>,
44 dependencies: Vec<Dependency>,
46 capabilities: Vec<String>,
48 tags: Vec<String>,
50 requirements: SystemRequirements,
52 entry_point: String,
54 metadata: HashMap<String, serde_json::Value>,
56}
57
58impl PluginInfo {
59 pub fn new(name: &str, version: &str, description: &str, dependencies: &[&str]) -> Self {
89 let version = Version::parse(version).expect("Invalid version string");
90
91 let deps = dependencies.iter().filter_map(|dep| Dependency::parse(dep).ok()).collect();
92
93 Self {
94 name: name.to_string(),
95 version,
96 description: description.to_string(),
97 author: None,
98 homepage: None,
99 license: None,
100 dependencies: deps,
101 capabilities: Vec::new(),
102 tags: Vec::new(),
103 requirements: SystemRequirements::default(),
104 entry_point: String::new(),
105 metadata: HashMap::new(),
106 }
107 }
108
109 pub fn name(&self) -> &str {
111 &self.name
112 }
113
114 pub fn version(&self) -> &Version {
116 &self.version
117 }
118
119 pub fn description(&self) -> &str {
121 &self.description
122 }
123
124 pub fn author(&self) -> Option<&str> {
126 self.author.as_deref()
127 }
128
129 pub fn set_author(&mut self, author: String) {
131 self.author = Some(author);
132 }
133
134 pub fn homepage(&self) -> Option<&str> {
136 self.homepage.as_deref()
137 }
138
139 pub fn set_homepage(&mut self, homepage: String) {
141 self.homepage = Some(homepage);
142 }
143
144 pub fn license(&self) -> Option<&str> {
146 self.license.as_deref()
147 }
148
149 pub fn set_license(&mut self, license: String) {
151 self.license = Some(license);
152 }
153
154 pub fn dependencies(&self) -> &[Dependency] {
156 &self.dependencies
157 }
158
159 pub fn add_dependency(&mut self, dependency: Dependency) {
161 self.dependencies.push(dependency);
162 }
163
164 pub fn capabilities(&self) -> &[String] {
166 &self.capabilities
167 }
168
169 pub fn add_capability(&mut self, capability: String) {
171 self.capabilities.push(capability);
172 }
173
174 pub fn tags(&self) -> &[String] {
176 &self.tags
177 }
178
179 pub fn add_tag(&mut self, tag: String) {
181 self.tags.push(tag);
182 }
183
184 pub fn requirements(&self) -> &SystemRequirements {
186 &self.requirements
187 }
188
189 pub fn set_requirements(&mut self, requirements: SystemRequirements) {
191 self.requirements = requirements;
192 }
193
194 pub fn entry_point(&self) -> &str {
196 &self.entry_point
197 }
198
199 pub fn set_entry_point(&mut self, entry_point: String) {
201 self.entry_point = entry_point;
202 }
203
204 pub fn metadata(&self) -> &HashMap<String, serde_json::Value> {
206 &self.metadata
207 }
208
209 pub fn add_metadata(&mut self, key: String, value: serde_json::Value) {
211 self.metadata.insert(key, value);
212 }
213
214 pub fn is_compatible_with(&self, name: &str, version: &str) -> bool {
225 if let Ok(dep_version) = Version::parse(version) {
226 for dep in &self.dependencies {
227 if dep.name == name {
228 return dep.requirement.matches(&dep_version);
229 }
230 }
231 }
232 true }
234
235 pub fn validate(&self) -> Result<()> {
241 if self.name.is_empty() {
242 return Err(TrustformersError::invalid_config(
243 "Plugin name cannot be empty".to_string(),
244 ));
245 }
246
247 if self.description.is_empty() {
248 return Err(TrustformersError::invalid_config(
249 "Plugin description cannot be empty".to_string(),
250 ));
251 }
252
253 if self.entry_point.is_empty() {
254 return Err(TrustformersError::invalid_config(
255 "Plugin entry point cannot be empty".to_string(),
256 ));
257 }
258
259 for dep in &self.dependencies {
261 dep.validate()?;
262 }
263
264 self.requirements.validate()?;
266
267 Ok(())
268 }
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct Dependency {
277 pub name: String,
279 pub requirement: VersionReq,
281 pub optional: bool,
283 pub features: Vec<String>,
285}
286
287impl Dependency {
288 pub fn new(name: &str, requirement: &str) -> Result<Self> {
299 let req = VersionReq::parse(requirement).map_err(|e| {
300 TrustformersError::invalid_config(format!(
301 "Invalid version requirement '{}': {}",
302 requirement, e
303 ))
304 })?;
305
306 Ok(Self {
307 name: name.to_string(),
308 requirement: req,
309 optional: false,
310 features: Vec::new(),
311 })
312 }
313
314 pub fn parse(spec: &str) -> Result<Self> {
329 let parts: Vec<&str> = spec.splitn(2, ' ').collect();
330 let name = parts[0].to_string();
331
332 let requirement = if parts.len() > 1 {
333 VersionReq::parse(parts[1].trim()).map_err(|e| {
334 TrustformersError::invalid_config(format!(
335 "Invalid dependency spec '{}': {}",
336 spec, e
337 ))
338 })?
339 } else {
340 VersionReq::STAR
341 };
342
343 Ok(Self {
344 name,
345 requirement,
346 optional: false,
347 features: Vec::new(),
348 })
349 }
350
351 pub fn optional(mut self) -> Self {
353 self.optional = true;
354 self
355 }
356
357 pub fn with_features(mut self, features: Vec<String>) -> Self {
359 self.features = features;
360 self
361 }
362
363 pub fn validate(&self) -> Result<()> {
365 if self.name.is_empty() {
366 return Err(TrustformersError::invalid_config(
367 "Dependency name cannot be empty".to_string(),
368 ));
369 }
370 Ok(())
371 }
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize, Default)]
379pub struct SystemRequirements {
380 pub min_memory_mb: Option<u64>,
382 pub min_disk_mb: Option<u64>,
384 pub cpu_features: Vec<String>,
386 pub gpu: Option<GpuRequirements>,
388 pub os: Vec<String>,
390 pub arch: Vec<String>,
392}
393
394impl SystemRequirements {
395 pub fn new() -> Self {
397 Self::default()
398 }
399
400 pub fn min_memory_mb(mut self, memory_mb: u64) -> Self {
402 self.min_memory_mb = Some(memory_mb);
403 self
404 }
405
406 pub fn min_disk_mb(mut self, disk_mb: u64) -> Self {
408 self.min_disk_mb = Some(disk_mb);
409 self
410 }
411
412 pub fn cpu_feature(mut self, feature: String) -> Self {
414 self.cpu_features.push(feature);
415 self
416 }
417
418 pub fn gpu(mut self, gpu: GpuRequirements) -> Self {
420 self.gpu = Some(gpu);
421 self
422 }
423
424 pub fn os(mut self, os: String) -> Self {
426 self.os.push(os);
427 self
428 }
429
430 pub fn arch(mut self, arch: String) -> Self {
432 self.arch.push(arch);
433 self
434 }
435
436 pub fn validate(&self) -> Result<()> {
438 if let Some(gpu) = &self.gpu {
439 gpu.validate()?;
440 }
441 Ok(())
442 }
443}
444
445#[derive(Debug, Clone, Serialize, Deserialize)]
447pub struct GpuRequirements {
448 pub min_memory_mb: u64,
450 pub compute_capability: Option<String>,
452 pub vendors: Vec<String>,
454 pub apis: Vec<String>,
456}
457
458impl GpuRequirements {
459 pub fn new(min_memory_mb: u64) -> Self {
461 Self {
462 min_memory_mb,
463 compute_capability: None,
464 vendors: Vec::new(),
465 apis: Vec::new(),
466 }
467 }
468
469 pub fn compute_capability(mut self, capability: String) -> Self {
471 self.compute_capability = Some(capability);
472 self
473 }
474
475 pub fn vendor(mut self, vendor: String) -> Self {
477 self.vendors.push(vendor);
478 self
479 }
480
481 pub fn api(mut self, api: String) -> Self {
483 self.apis.push(api);
484 self
485 }
486
487 pub fn validate(&self) -> Result<()> {
489 if self.min_memory_mb == 0 {
490 return Err(TrustformersError::invalid_config(
491 "GPU memory requirement must be greater than 0".to_string(),
492 ));
493 }
494 Ok(())
495 }
496}