use crate::Result;
use async_trait::async_trait;
use std::fmt::Debug;
pub use peat_schema::node::v1::Phase;
pub trait PhaseExt {
fn as_str(&self) -> &'static str;
const BOOTSTRAP: Phase;
const SQUAD: Phase;
const HIERARCHICAL: Phase;
}
impl PhaseExt for Phase {
fn as_str(&self) -> &'static str {
match self {
Phase::Unspecified => "unspecified",
Phase::Discovery => "discovery",
Phase::Cell => "cell",
Phase::Hierarchy => "hierarchical",
}
}
const BOOTSTRAP: Phase = Phase::Discovery;
const SQUAD: Phase = Phase::Cell;
const HIERARCHICAL: Phase = Phase::Hierarchy;
}
#[async_trait]
pub trait Platform: Send + Sync + Debug {
async fn initialize(&mut self) -> Result<()>;
async fn update(&mut self) -> Result<()>;
fn phase(&self) -> Phase;
async fn transition_to(&mut self, phase: Phase) -> Result<()>;
async fn shutdown(&mut self) -> Result<()>;
}
#[async_trait]
pub trait CapabilityProvider: Send + Sync + Debug {
fn static_capabilities(&self) -> Vec<String>;
fn dynamic_capabilities(&self) -> Vec<String>;
fn has_capability(&self, capability: &str) -> bool;
fn capability_confidence(&self, capability: &str) -> f32;
}
#[async_trait]
pub trait MessageRouter: Send + Sync + Debug {
async fn route(&mut self, message: Vec<u8>) -> Result<()>;
fn is_route_valid(&self, from: &str, to: &str) -> bool;
fn valid_targets(&self) -> Vec<String>;
}
#[async_trait]
pub trait PhaseTransition: Send + Sync + Debug {
fn can_transition_to(&self, phase: Phase) -> bool;
async fn perform_transition(&mut self, from: Phase, to: Phase) -> Result<()>;
fn transition_progress(&self) -> f32;
}
#[async_trait]
pub trait Storage: Send + Sync + Debug {
async fn store(&mut self, key: &str, value: serde_json::Value) -> Result<()>;
async fn retrieve(&self, key: &str) -> Result<Option<serde_json::Value>>;
async fn delete(&mut self, key: &str) -> Result<()>;
async fn query(&self, query: &str) -> Result<Vec<serde_json::Value>>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_phase_as_str() {
assert_eq!(Phase::Unspecified.as_str(), "unspecified");
assert_eq!(Phase::Discovery.as_str(), "discovery");
assert_eq!(Phase::Cell.as_str(), "cell");
assert_eq!(Phase::Hierarchy.as_str(), "hierarchical");
}
#[test]
fn test_phase_legacy_constants() {
assert_eq!(Phase::BOOTSTRAP, Phase::Discovery);
assert_eq!(Phase::SQUAD, Phase::Cell);
assert_eq!(Phase::HIERARCHICAL, Phase::Hierarchy);
}
#[test]
fn test_phase_as_str_all_variants() {
let phases = vec![
Phase::Unspecified,
Phase::Discovery,
Phase::Cell,
Phase::Hierarchy,
];
for phase in phases {
let s = phase.as_str();
assert!(!s.is_empty());
assert!(s.chars().all(|c| c.is_ascii_lowercase() || c == '_'));
}
}
#[test]
fn test_phase_enum_values() {
assert_eq!(Phase::Unspecified as i32, 0);
assert_eq!(Phase::Discovery as i32, 1);
assert_eq!(Phase::Cell as i32, 2);
assert_eq!(Phase::Hierarchy as i32, 3);
}
#[test]
fn test_phase_pattern_matching() {
let phase = Phase::Discovery;
match phase {
Phase::Unspecified => panic!("Wrong phase"),
Phase::Discovery => {} Phase::Cell => panic!("Wrong phase"),
Phase::Hierarchy => panic!("Wrong phase"),
}
}
#[test]
fn test_phase_equality() {
assert_eq!(Phase::Discovery, Phase::Discovery);
assert_ne!(Phase::Discovery, Phase::Cell);
assert_eq!(Phase::BOOTSTRAP, Phase::Discovery); }
}