1use std::any::Any;
16use std::collections::HashMap;
17use std::fmt;
18
19use super::config::{EcosystemConfig, ModuleConfig};
20use super::zero_copy::{SharedArrayView, SharedArrayViewMut};
21use crate::error::{CoreError, CoreResult, ErrorContext, ErrorLocation};
22
23pub trait Identifiable {
25 fn id(&self) -> &str;
27
28 fn name(&self) -> &str;
30
31 fn component_type(&self) -> &str;
33
34 fn metadata(&self) -> HashMap<String, String> {
36 HashMap::new()
37 }
38}
39
40pub trait Configurable {
42 fn configure(&mut self, config: &EcosystemConfig) -> CoreResult<()>;
44
45 fn configure_module(&mut self, config: &ModuleConfig) -> CoreResult<()>;
47
48 fn get_config(&self) -> HashMap<String, String>;
50
51 fn reset_config(&mut self);
53
54 fn validate_config(&self) -> CoreResult<()>;
56}
57
58pub trait DataProvider<T> {
60 fn len(&self) -> usize;
62
63 fn is_empty(&self) -> bool {
65 self.len() == 0
66 }
67
68 fn view(&self) -> CoreResult<SharedArrayView<'_, T>>;
70
71 fn shape(&self) -> &[usize];
73
74 fn dtype(&self) -> &str;
76
77 fn is_contiguous(&self) -> bool;
79}
80
81pub trait DataConsumer<T> {
83 fn consume<P: DataProvider<T>>(&mut self, provider: &P) -> CoreResult<()>;
85
86 fn consume_slice(&mut self, data: &[T]) -> CoreResult<()>;
88
89 fn consume_view(&mut self, view: SharedArrayView<'_, T>) -> CoreResult<()>;
91
92 fn expected_shape(&self) -> Option<&[usize]>;
94
95 fn can_accept_shape(&self, shape: &[usize]) -> bool;
97}
98
99pub trait MutableDataProvider<T>: DataProvider<T> {
101 fn view_mut(&mut self) -> CoreResult<SharedArrayViewMut<'_, T>>;
103
104 fn apply<F>(&mut self, f: F) -> CoreResult<()>
106 where
107 F: Fn(&mut T);
108
109 fn clear(&mut self);
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
115pub enum Capability {
116 Parallel,
118 GpuAcceleration,
120 Simd,
122 Streaming,
124 Distributed,
126 Serializable,
128 Checkpointing,
130 ThreadSafe,
132 Async,
134 MemoryMapped,
136 ZeroCopy,
138 Batched,
140 Custom(&'static str),
142}
143
144impl fmt::Display for Capability {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 match self {
147 Capability::Parallel => write!(f, "parallel"),
148 Capability::GpuAcceleration => write!(f, "gpu"),
149 Capability::Simd => write!(f, "simd"),
150 Capability::Streaming => write!(f, "streaming"),
151 Capability::Distributed => write!(f, "distributed"),
152 Capability::Serializable => write!(f, "serializable"),
153 Capability::Checkpointing => write!(f, "checkpointing"),
154 Capability::ThreadSafe => write!(f, "thread-safe"),
155 Capability::Async => write!(f, "async"),
156 Capability::MemoryMapped => write!(f, "mmap"),
157 Capability::ZeroCopy => write!(f, "zero-copy"),
158 Capability::Batched => write!(f, "batched"),
159 Capability::Custom(name) => write!(f, "custom:{name}"),
160 }
161 }
162}
163
164pub trait ModuleCapability {
166 fn capabilities(&self) -> Vec<Capability>;
168
169 fn has_capability(&self, cap: Capability) -> bool {
171 self.capabilities().contains(&cap)
172 }
173
174 fn required_capabilities(&self, operation: &str) -> Vec<Capability>;
176
177 fn can_perform(&self, operation: &str) -> bool {
179 let required = self.required_capabilities(operation);
180 required.iter().all(|cap| self.has_capability(*cap))
181 }
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186pub enum SerializationFormat {
187 Json,
189 MessagePack,
191 Binary,
193 Cbor,
195 Protobuf,
197}
198
199pub trait Serializable {
201 fn supported_formats(&self) -> Vec<SerializationFormat>;
203
204 fn serialize(&self, format: SerializationFormat) -> CoreResult<Vec<u8>>;
206
207 fn deserialize(&mut self, data: &[u8], format: SerializationFormat) -> CoreResult<()>;
209
210 fn estimated_size(&self, format: SerializationFormat) -> usize;
212}
213
214pub trait CrossModuleOperator<Input, Output> {
216 fn apply(&self, input: &Input) -> CoreResult<Output>;
218
219 fn apply_inplace(&self, data: &mut Input) -> CoreResult<()>
221 where
222 Input: From<Output>;
223
224 fn operator_name(&self) -> &str;
226
227 fn input_info(&self) -> &str;
229
230 fn output_info(&self) -> &str;
232
233 fn is_deterministic(&self) -> bool;
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Hash)]
239pub struct ApiVersion {
240 pub major: u32,
242 pub minor: u32,
244 pub patch: u32,
246}
247
248impl ApiVersion {
249 #[must_use]
251 pub const fn new(major: u32, minor: u32, patch: u32) -> Self {
252 Self {
253 major,
254 minor,
255 patch,
256 }
257 }
258
259 #[must_use]
261 pub const fn is_compatible(&self, other: &Self) -> bool {
262 self.major == other.major && self.minor >= other.minor
263 }
264
265 #[must_use]
267 pub const fn is_newer_than(&self, other: &Self) -> bool {
268 if self.major != other.major {
269 return self.major > other.major;
270 }
271 if self.minor != other.minor {
272 return self.minor > other.minor;
273 }
274 self.patch > other.patch
275 }
276}
277
278impl fmt::Display for ApiVersion {
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
281 }
282}
283
284pub trait VersionedInterface {
286 fn version(&self) -> ApiVersion;
288
289 fn is_compatible_with(&self, version: &ApiVersion) -> bool {
291 self.version().is_compatible(version)
292 }
293
294 fn minimum_version(&self) -> ApiVersion;
296
297 fn deprecated_features(&self) -> Vec<String>;
299}
300
301pub trait ModuleInterface:
303 Identifiable + Configurable + ModuleCapability + VersionedInterface
304{
305 fn initialize(&mut self) -> CoreResult<()>;
307
308 fn shutdown(&mut self) -> CoreResult<()>;
310
311 fn health_check(&self) -> CoreResult<HealthStatus>;
313
314 fn statistics(&self) -> HashMap<String, f64>;
316
317 fn reset(&mut self) -> CoreResult<()>;
319}
320
321#[derive(Debug, Clone, PartialEq, Eq)]
323pub enum HealthStatus {
324 Healthy,
326 Degraded(String),
328 Unhealthy(String),
330 Unknown,
332}
333
334impl fmt::Display for HealthStatus {
335 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336 match self {
337 HealthStatus::Healthy => write!(f, "healthy"),
338 HealthStatus::Degraded(msg) => write!(f, "degraded: {msg}"),
339 HealthStatus::Unhealthy(msg) => write!(f, "unhealthy: {msg}"),
340 HealthStatus::Unknown => write!(f, "unknown"),
341 }
342 }
343}
344
345#[derive(Debug, Clone, Default)]
347pub struct ResourceUsage {
348 pub memory_bytes: usize,
350 pub cpu_percent: f32,
352 pub gpu_memory_bytes: usize,
354 pub thread_count: usize,
356 pub file_handles: usize,
358 pub custom: HashMap<String, f64>,
360}
361
362pub trait ResourceAware {
364 fn resource_usage(&self) -> ResourceUsage;
366
367 fn resource_limits(&self) -> ResourceUsage;
369
370 fn set_resource_limits(&mut self, limits: ResourceUsage) -> CoreResult<()>;
372
373 fn within_limits(&self) -> bool {
375 let usage = self.resource_usage();
376 let limits = self.resource_limits();
377
378 if limits.memory_bytes > 0 && usage.memory_bytes > limits.memory_bytes {
379 return false;
380 }
381 if limits.cpu_percent > 0.0 && usage.cpu_percent > limits.cpu_percent {
382 return false;
383 }
384 if limits.gpu_memory_bytes > 0 && usage.gpu_memory_bytes > limits.gpu_memory_bytes {
385 return false;
386 }
387 if limits.thread_count > 0 && usage.thread_count > limits.thread_count {
388 return false;
389 }
390 true
391 }
392
393 fn release_resources(&mut self) -> CoreResult<usize>;
395
396 fn estimate_resources(&self, operation: &str, input_size: usize) -> ResourceUsage;
398}
399
400#[derive(Debug, Clone)]
402pub struct DiagnosticInfo {
403 pub component: String,
405 pub level: DiagnosticLevel,
407 pub message: String,
409 pub context: HashMap<String, String>,
411 pub timestamp: std::time::SystemTime,
413}
414
415#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
417pub enum DiagnosticLevel {
418 Trace,
420 Debug,
422 Info,
424 Warning,
426 Error,
428}
429
430impl fmt::Display for DiagnosticLevel {
431 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432 match self {
433 DiagnosticLevel::Trace => write!(f, "TRACE"),
434 DiagnosticLevel::Debug => write!(f, "DEBUG"),
435 DiagnosticLevel::Info => write!(f, "INFO"),
436 DiagnosticLevel::Warning => write!(f, "WARN"),
437 DiagnosticLevel::Error => write!(f, "ERROR"),
438 }
439 }
440}
441
442pub trait Diagnosable {
444 fn diagnostics(&self) -> Vec<DiagnosticInfo>;
446
447 fn diagnostics_at_level(&self, min_level: DiagnosticLevel) -> Vec<DiagnosticInfo> {
449 self.diagnostics()
450 .into_iter()
451 .filter(|d| d.level >= min_level)
452 .collect()
453 }
454
455 fn clear_diagnostics(&mut self);
457
458 fn enable_diagnostics(&mut self, enabled: bool);
460
461 fn diagnostics_enabled(&self) -> bool;
463
464 fn diagnostic_summary(&self) -> String {
466 let diags = self.diagnostics();
467 let errors = diags
468 .iter()
469 .filter(|d| d.level == DiagnosticLevel::Error)
470 .count();
471 let warnings = diags
472 .iter()
473 .filter(|d| d.level == DiagnosticLevel::Warning)
474 .count();
475 format!(
476 "{} diagnostics ({} errors, {} warnings)",
477 diags.len(),
478 errors,
479 warnings
480 )
481 }
482}
483
484pub trait Composable {
486 fn compose<Other: Composable>(&self, other: &Other) -> CoreResult<Box<dyn Any>>;
488
489 fn can_compose_with<Other: Composable>(&self, other: &Other) -> bool;
491
492 fn composition_requirements(&self) -> Vec<String>;
494
495 fn composition_outputs(&self) -> Vec<String>;
497}
498
499pub trait PipelineStage<Input, Output> {
501 fn process(&self, input: Input) -> CoreResult<Output>;
503
504 fn stage_name(&self) -> &str;
506
507 fn is_ready(&self) -> bool;
509
510 fn estimated_time_ms(&self, input_size: usize) -> f64;
512}
513
514pub trait Chainable<T> {
516 fn chain<F, U>(self, f: F) -> Chain<Self, F>
518 where
519 Self: Sized,
520 F: Fn(T) -> U;
521
522 fn map<F, U>(self, f: F) -> Map<Self, F>
524 where
525 Self: Sized,
526 F: Fn(T) -> U;
527
528 fn filter<F>(self, f: F) -> Filter<Self, F>
530 where
531 Self: Sized,
532 F: Fn(&T) -> bool;
533}
534
535#[derive(Debug)]
537pub struct Chain<A, F> {
538 inner: A,
539 f: F,
540}
541
542impl<A, F> Chain<A, F> {
543 #[must_use]
545 pub const fn new(inner: A, f: F) -> Self {
546 Self { inner, f }
547 }
548
549 #[must_use]
551 pub const fn inner(&self) -> &A {
552 &self.inner
553 }
554}
555
556#[derive(Debug)]
558pub struct Map<A, F> {
559 inner: A,
560 f: F,
561}
562
563impl<A, F> Map<A, F> {
564 #[must_use]
566 pub const fn new(inner: A, f: F) -> Self {
567 Self { inner, f }
568 }
569}
570
571#[derive(Debug)]
573pub struct Filter<A, F> {
574 inner: A,
575 predicate: F,
576}
577
578impl<A, F> Filter<A, F> {
579 #[must_use]
581 pub const fn new(inner: A, predicate: F) -> Self {
582 Self { inner, predicate }
583 }
584}
585
586pub trait Observer<T> {
588 fn on_next(&mut self, value: T);
590
591 fn on_error(&mut self, error: CoreError);
593
594 fn on_complete(&mut self);
596}
597
598pub trait Observable<T> {
600 fn subscribe(&mut self, observer: Box<dyn Observer<T> + Send>);
602
603 fn unsubscribe(&mut self, observer_id: usize);
605
606 fn subscriber_count(&self) -> usize;
608}
609
610#[cfg(test)]
611mod tests {
612 use super::*;
613
614 #[test]
615 fn test_api_version() {
616 let v1 = ApiVersion::new(1, 2, 3);
617 let v2 = ApiVersion::new(1, 3, 0);
618 let v3 = ApiVersion::new(2, 0, 0);
619
620 assert!(v2.is_compatible(&v1));
621 assert!(!v1.is_compatible(&v2));
622 assert!(!v3.is_compatible(&v1));
623
624 assert!(v2.is_newer_than(&v1));
625 assert!(v3.is_newer_than(&v2));
626 }
627
628 #[test]
629 fn test_version_display() {
630 let v = ApiVersion::new(1, 2, 3);
631 assert_eq!(v.to_string(), "1.2.3");
632 }
633
634 #[test]
635 fn test_capability_display() {
636 assert_eq!(Capability::Parallel.to_string(), "parallel");
637 assert_eq!(Capability::GpuAcceleration.to_string(), "gpu");
638 assert_eq!(Capability::Custom("test").to_string(), "custom:test");
639 }
640
641 #[test]
642 fn test_health_status() {
643 assert_eq!(HealthStatus::Healthy.to_string(), "healthy");
644 assert!(HealthStatus::Degraded("slow".into())
645 .to_string()
646 .contains("slow"));
647 assert!(HealthStatus::Unhealthy("failed".into())
648 .to_string()
649 .contains("failed"));
650 }
651
652 #[test]
653 fn test_resource_usage() {
654 let usage = ResourceUsage {
655 memory_bytes: 1024,
656 cpu_percent: 50.0,
657 thread_count: 4,
658 ..Default::default()
659 };
660
661 assert_eq!(usage.memory_bytes, 1024);
662 assert_eq!(usage.cpu_percent, 50.0);
663 assert_eq!(usage.thread_count, 4);
664 }
665
666 #[test]
667 fn test_diagnostic_level_ordering() {
668 assert!(DiagnosticLevel::Error > DiagnosticLevel::Warning);
669 assert!(DiagnosticLevel::Warning > DiagnosticLevel::Info);
670 assert!(DiagnosticLevel::Info > DiagnosticLevel::Debug);
671 assert!(DiagnosticLevel::Debug > DiagnosticLevel::Trace);
672 }
673
674 #[test]
675 fn test_diagnostic_info() {
676 let info = DiagnosticInfo {
677 component: "test".into(),
678 level: DiagnosticLevel::Info,
679 message: "test message".into(),
680 context: HashMap::new(),
681 timestamp: std::time::SystemTime::now(),
682 };
683
684 assert_eq!(info.component, "test");
685 assert_eq!(info.level, DiagnosticLevel::Info);
686 }
687
688 #[test]
689 fn test_chain_combinator() {
690 let chain = Chain::new(42, |x: i32| x * 2);
691 assert_eq!(*chain.inner(), 42);
692 }
693
694 #[test]
695 fn test_serialization_format() {
696 let format = SerializationFormat::Json;
697 assert_eq!(format, SerializationFormat::Json);
698 }
699}