1pub mod SpineConnection;
7
8pub const SPINE_PROTOCOL_VERSION:&str = "1.0.0";
14
15pub const DEFAULT_MOUNTAIN_ENDPOINT:&str = "127.0.0.1:50050";
17
18pub const DEFAULT_CONNECTION_TIMEOUT_MS:u64 = 5000;
20
21pub const DEFAULT_HEARTBEAT_INTERVAL_SEC:u64 = 30;
23
24pub const DEFAULT_MESSAGE_BUFFER_SIZE:usize = 8192;
26
27#[derive(Debug, Clone)]
29pub struct ProtocolConfig {
30 pub version:String,
32 pub mountain_endpoint:String,
34 pub connection_timeout_ms:u64,
36 pub heartbeat_interval_sec:u64,
38 pub message_buffer_size:usize,
40 pub enable_tls:bool,
42 pub enable_compression:bool,
44}
45
46impl ProtocolConfig {
47 pub fn new() -> Self {
49 Self {
50 version:SPINE_PROTOCOL_VERSION.to_string(),
51 mountain_endpoint:DEFAULT_MOUNTAIN_ENDPOINT.to_string(),
52 connection_timeout_ms:DEFAULT_CONNECTION_TIMEOUT_MS,
53 heartbeat_interval_sec:DEFAULT_HEARTBEAT_INTERVAL_SEC,
54 message_buffer_size:DEFAULT_MESSAGE_BUFFER_SIZE,
55 enable_tls:false,
56 enable_compression:false,
57 }
58 }
59
60 pub fn with_mountain_endpoint(mut self, endpoint:String) -> Self {
62 self.mountain_endpoint = endpoint;
63 self
64 }
65
66 pub fn with_connection_timeout(mut self, timeout_ms:u64) -> Self {
68 self.connection_timeout_ms = timeout_ms;
69 self
70 }
71
72 pub fn with_heartbeat_interval(mut self, interval_sec:u64) -> Self {
74 self.heartbeat_interval_sec = interval_sec;
75 self
76 }
77
78 pub fn with_tls(mut self, enable:bool) -> Self {
80 self.enable_tls = enable;
81 self
82 }
83
84 pub fn with_compression(mut self, enable:bool) -> Self {
86 self.enable_compression = enable;
87 self
88 }
89}
90
91impl Default for ProtocolConfig {
92 fn default() -> Self { Self::new() }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
97pub enum MessageType {
98 Heartbeat = 0,
100 Register = 1,
102 Unregister = 2,
104 Event = 3,
106 Request = 4,
108 Response = 5,
110 Error = 6,
112}
113
114impl MessageType {
115 pub fn as_u32(self) -> u32 { self as u32 }
117
118 pub fn from_u32(value:u32) -> Option<Self> {
120 match value {
121 0 => Some(Self::Heartbeat),
122 1 => Some(Self::Register),
123 2 => Some(Self::Unregister),
124 3 => Some(Self::Event),
125 4 => Some(Self::Request),
126 5 => Some(Self::Response),
127 6 => Some(Self::Error),
128 _ => None,
129 }
130 }
131}
132
133#[derive(Debug, thiserror::Error)]
135pub enum ProtocolError {
136 #[error("Connection error: {0}")]
138 ConnectionError(String),
139
140 #[error("Serialization error: {0}")]
142 SerializationError(String),
143
144 #[error("Deserialization error: {0}")]
146 DeserializationError(String),
147
148 #[error("Invalid message: {0}")]
150 InvalidMessage(String),
151
152 #[error("Timeout error")]
154 Timeout,
155
156 #[error("Protocol error: {0}")]
158 ProtocolError(String),
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
166 fn test_protocol_config_default() {
167 let config = ProtocolConfig::default();
168 assert_eq!(config.mountain_endpoint, DEFAULT_MOUNTAIN_ENDPOINT);
169 assert_eq!(config.connection_timeout_ms, DEFAULT_CONNECTION_TIMEOUT_MS);
170 }
171
172 #[test]
173 fn test_protocol_config_builder() {
174 let config = ProtocolConfig::default()
175 .with_mountain_endpoint("127.0.0.1:60000".to_string())
176 .with_connection_timeout(10000)
177 .with_heartbeat_interval(60);
178
179 assert_eq!(config.mountain_endpoint, "127.0.0.1:60000");
180 assert_eq!(config.connection_timeout_ms, 10000);
181 assert_eq!(config.heartbeat_interval_sec, 60);
182 }
183
184 #[test]
185 fn test_message_type_conversion() {
186 let msg_type = MessageType::Heartbeat;
187 assert_eq!(msg_type.as_u32(), 0);
188
189 let converted = MessageType::from_u32(0);
190 assert_eq!(converted, Some(MessageType::Heartbeat));
191
192 let invalid = MessageType::from_u32(999);
193 assert_eq!(invalid, None);
194 }
195}