1pub mod SpineConnection;
7
8pub const SPINE_PROTOCOL_VERSION:&str = "1.0.0";
13
14pub const DEFAULT_MOUNTAIN_ENDPOINT:&str = "127.0.0.1:50050";
16
17pub const DEFAULT_CONNECTION_TIMEOUT_MS:u64 = 5000;
19
20pub const DEFAULT_HEARTBEAT_INTERVAL_SEC:u64 = 30;
22
23pub const DEFAULT_MESSAGE_BUFFER_SIZE:usize = 8192;
25
26#[derive(Debug, Clone)]
28pub struct ProtocolConfig {
29 pub version:String,
31 pub mountain_endpoint:String,
33 pub connection_timeout_ms:u64,
35 pub heartbeat_interval_sec:u64,
37 pub message_buffer_size:usize,
39 pub enable_tls:bool,
41 pub enable_compression:bool,
43}
44
45impl ProtocolConfig {
46 pub fn new() -> Self {
48 Self {
49 version:SPINE_PROTOCOL_VERSION.to_string(),
50 mountain_endpoint:DEFAULT_MOUNTAIN_ENDPOINT.to_string(),
51 connection_timeout_ms:DEFAULT_CONNECTION_TIMEOUT_MS,
52 heartbeat_interval_sec:DEFAULT_HEARTBEAT_INTERVAL_SEC,
53 message_buffer_size:DEFAULT_MESSAGE_BUFFER_SIZE,
54 enable_tls:false,
55 enable_compression:false,
56 }
57 }
58
59 pub fn with_mountain_endpoint(mut self, endpoint:String) -> Self {
61 self.mountain_endpoint = endpoint;
62 self
63 }
64
65 pub fn with_connection_timeout(mut self, timeout_ms:u64) -> Self {
67 self.connection_timeout_ms = timeout_ms;
68 self
69 }
70
71 pub fn with_heartbeat_interval(mut self, interval_sec:u64) -> Self {
73 self.heartbeat_interval_sec = interval_sec;
74 self
75 }
76
77 pub fn with_tls(mut self, enable:bool) -> Self {
79 self.enable_tls = enable;
80 self
81 }
82
83 pub fn with_compression(mut self, enable:bool) -> Self {
85 self.enable_compression = enable;
86 self
87 }
88}
89
90impl Default for ProtocolConfig {
91 fn default() -> Self { Self::new() }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
96pub enum MessageType {
97 Heartbeat = 0,
99 Register = 1,
101 Unregister = 2,
103 Event = 3,
105 Request = 4,
107 Response = 5,
109 Error = 6,
111}
112
113impl MessageType {
114 pub fn as_u32(self) -> u32 { self as u32 }
116
117 pub fn from_u32(value:u32) -> Option<Self> {
119 match value {
120 0 => Some(Self::Heartbeat),
121 1 => Some(Self::Register),
122 2 => Some(Self::Unregister),
123 3 => Some(Self::Event),
124 4 => Some(Self::Request),
125 5 => Some(Self::Response),
126 6 => Some(Self::Error),
127 _ => None,
128 }
129 }
130}
131
132#[derive(Debug, thiserror::Error)]
134pub enum ProtocolError {
135#[error("Connection error: {0}")]
137ConnectionError(String),
138
139#[error("Serialization error: {0}")]
141SerializationError(String),
142
143#[error("Deserialization error: {0}")]
145DeserializationError(String),
146
147#[error("Invalid message: {0}")]
149InvalidMessage(String),
150
151#[error("Timeout error")]
153Timeout,
154
155#[error("Protocol error: {0}")]
157ProtocolError(String),
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_protocol_config_default() {
166 let config = ProtocolConfig::default();
167 assert_eq!(config.mountain_endpoint, DEFAULT_MOUNTAIN_ENDPOINT);
168 assert_eq!(config.connection_timeout_ms, DEFAULT_CONNECTION_TIMEOUT_MS);
169 }
170
171 #[test]
172 fn test_protocol_config_builder() {
173 let config = ProtocolConfig::default()
174 .with_mountain_endpoint("127.0.0.1:60000".to_string())
175 .with_connection_timeout(10000)
176 .with_heartbeat_interval(60);
177
178 assert_eq!(config.mountain_endpoint, "127.0.0.1:60000");
179 assert_eq!(config.connection_timeout_ms, 10000);
180 assert_eq!(config.heartbeat_interval_sec, 60);
181 }
182
183 #[test]
184 fn test_message_type_conversion() {
185 let msg_type = MessageType::Heartbeat;
186 assert_eq!(msg_type.as_u32(), 0);
187
188 let converted = MessageType::from_u32(0);
189 assert_eq!(converted, Some(MessageType::Heartbeat));
190
191 let invalid = MessageType::from_u32(999);
192 assert_eq!(invalid, None);
193 }
194}