Skip to main content

peat_protocol/
traits.rs

1//! Core trait definitions for the Peat protocol
2
3use crate::Result;
4use async_trait::async_trait;
5use std::fmt::Debug;
6
7// Re-export Phase from cap_schema
8pub use peat_schema::node::v1::Phase;
9
10/// Extension trait for Phase enum
11pub trait PhaseExt {
12    /// Get lowercase string representation
13    fn as_str(&self) -> &'static str;
14
15    /// Legacy compatibility constants
16    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    // Legacy compatibility - old names as aliases
32    const BOOTSTRAP: Phase = Phase::Discovery;
33    const SQUAD: Phase = Phase::Cell;
34    const HIERARCHICAL: Phase = Phase::Hierarchy;
35}
36
37/// Node lifecycle management
38#[async_trait]
39pub trait Platform: Send + Sync + Debug {
40    /// Initialize the platform with configuration
41    async fn initialize(&mut self) -> Result<()>;
42
43    /// Update node state (called at regular intervals)
44    async fn update(&mut self) -> Result<()>;
45
46    /// Get the current phase
47    fn phase(&self) -> Phase;
48
49    /// Transition to a new phase
50    async fn transition_to(&mut self, phase: Phase) -> Result<()>;
51
52    /// Shutdown the platform gracefully
53    async fn shutdown(&mut self) -> Result<()>;
54}
55
56/// Capability provider trait
57#[async_trait]
58pub trait CapabilityProvider: Send + Sync + Debug {
59    /// Get the platform's static capabilities
60    fn static_capabilities(&self) -> Vec<String>;
61
62    /// Get the platform's dynamic capabilities (may change over time)
63    fn dynamic_capabilities(&self) -> Vec<String>;
64
65    /// Check if the platform has a specific capability
66    fn has_capability(&self, capability: &str) -> bool;
67
68    /// Get confidence score for a capability (0.0 - 1.0)
69    fn capability_confidence(&self, capability: &str) -> f32;
70}
71
72/// Message routing trait
73#[async_trait]
74pub trait MessageRouter: Send + Sync + Debug {
75    /// Route a message according to hierarchical rules
76    async fn route(&mut self, message: Vec<u8>) -> Result<()>;
77
78    /// Check if a route is valid for the current phase
79    fn is_route_valid(&self, from: &str, to: &str) -> bool;
80
81    /// Get valid routing targets for this platform
82    fn valid_targets(&self) -> Vec<String>;
83}
84
85/// Phase transition logic
86#[async_trait]
87pub trait PhaseTransition: Send + Sync + Debug {
88    /// Check if the platform can transition to a new phase
89    fn can_transition_to(&self, phase: Phase) -> bool;
90
91    /// Perform the phase transition
92    async fn perform_transition(&mut self, from: Phase, to: Phase) -> Result<()>;
93
94    /// Get transition completion percentage (0.0 - 1.0)
95    fn transition_progress(&self) -> f32;
96}
97
98/// Storage abstraction for CRDT operations
99#[async_trait]
100pub trait Storage: Send + Sync + Debug {
101    /// Store a value with a key
102    async fn store(&mut self, key: &str, value: serde_json::Value) -> Result<()>;
103
104    /// Retrieve a value by key
105    async fn retrieve(&self, key: &str) -> Result<Option<serde_json::Value>>;
106
107    /// Delete a value by key
108    async fn delete(&mut self, key: &str) -> Result<()>;
109
110    /// Query values matching a predicate
111    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        // Ensure all Phase variants have string representations
136        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        // Test that Phase enum can be converted to/from i32
153        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 => {} // Expected
165            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); // Legacy constant
175    }
176}