1use crate::Result;
4use async_trait::async_trait;
5use std::fmt::Debug;
6
7pub use peat_schema::node::v1::Phase;
9
10pub trait PhaseExt {
12 fn as_str(&self) -> &'static str;
14
15 const BOOTSTRAP: Phase;
17 const SQUAD: Phase;
18 const HIERARCHICAL: Phase;
19}
20
21impl PhaseExt for Phase {
22 fn as_str(&self) -> &'static str {
23 match self {
24 Phase::Unspecified => "unspecified",
25 Phase::Discovery => "discovery",
26 Phase::Cell => "cell",
27 Phase::Hierarchy => "hierarchical",
28 }
29 }
30
31 const BOOTSTRAP: Phase = Phase::Discovery;
33 const SQUAD: Phase = Phase::Cell;
34 const HIERARCHICAL: Phase = Phase::Hierarchy;
35}
36
37#[async_trait]
39pub trait Platform: Send + Sync + Debug {
40 async fn initialize(&mut self) -> Result<()>;
42
43 async fn update(&mut self) -> Result<()>;
45
46 fn phase(&self) -> Phase;
48
49 async fn transition_to(&mut self, phase: Phase) -> Result<()>;
51
52 async fn shutdown(&mut self) -> Result<()>;
54}
55
56#[async_trait]
58pub trait CapabilityProvider: Send + Sync + Debug {
59 fn static_capabilities(&self) -> Vec<String>;
61
62 fn dynamic_capabilities(&self) -> Vec<String>;
64
65 fn has_capability(&self, capability: &str) -> bool;
67
68 fn capability_confidence(&self, capability: &str) -> f32;
70}
71
72#[async_trait]
74pub trait MessageRouter: Send + Sync + Debug {
75 async fn route(&mut self, message: Vec<u8>) -> Result<()>;
77
78 fn is_route_valid(&self, from: &str, to: &str) -> bool;
80
81 fn valid_targets(&self) -> Vec<String>;
83}
84
85#[async_trait]
87pub trait PhaseTransition: Send + Sync + Debug {
88 fn can_transition_to(&self, phase: Phase) -> bool;
90
91 async fn perform_transition(&mut self, from: Phase, to: Phase) -> Result<()>;
93
94 fn transition_progress(&self) -> f32;
96}
97
98#[async_trait]
100pub trait Storage: Send + Sync + Debug {
101 async fn store(&mut self, key: &str, value: serde_json::Value) -> Result<()>;
103
104 async fn retrieve(&self, key: &str) -> Result<Option<serde_json::Value>>;
106
107 async fn delete(&mut self, key: &str) -> Result<()>;
109
110 async fn query(&self, query: &str) -> Result<Vec<serde_json::Value>>;
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_phase_as_str() {
120 assert_eq!(Phase::Unspecified.as_str(), "unspecified");
121 assert_eq!(Phase::Discovery.as_str(), "discovery");
122 assert_eq!(Phase::Cell.as_str(), "cell");
123 assert_eq!(Phase::Hierarchy.as_str(), "hierarchical");
124 }
125
126 #[test]
127 fn test_phase_legacy_constants() {
128 assert_eq!(Phase::BOOTSTRAP, Phase::Discovery);
129 assert_eq!(Phase::SQUAD, Phase::Cell);
130 assert_eq!(Phase::HIERARCHICAL, Phase::Hierarchy);
131 }
132
133 #[test]
134 fn test_phase_as_str_all_variants() {
135 let phases = vec![
137 Phase::Unspecified,
138 Phase::Discovery,
139 Phase::Cell,
140 Phase::Hierarchy,
141 ];
142
143 for phase in phases {
144 let s = phase.as_str();
145 assert!(!s.is_empty());
146 assert!(s.chars().all(|c| c.is_ascii_lowercase() || c == '_'));
147 }
148 }
149
150 #[test]
151 fn test_phase_enum_values() {
152 assert_eq!(Phase::Unspecified as i32, 0);
154 assert_eq!(Phase::Discovery as i32, 1);
155 assert_eq!(Phase::Cell as i32, 2);
156 assert_eq!(Phase::Hierarchy as i32, 3);
157 }
158
159 #[test]
160 fn test_phase_pattern_matching() {
161 let phase = Phase::Discovery;
162 match phase {
163 Phase::Unspecified => panic!("Wrong phase"),
164 Phase::Discovery => {} Phase::Cell => panic!("Wrong phase"),
166 Phase::Hierarchy => panic!("Wrong phase"),
167 }
168 }
169
170 #[test]
171 fn test_phase_equality() {
172 assert_eq!(Phase::Discovery, Phase::Discovery);
173 assert_ne!(Phase::Discovery, Phase::Cell);
174 assert_eq!(Phase::BOOTSTRAP, Phase::Discovery); }
176}