Skip to main content

Grove/Protocol/
mod.rs

1//! Protocol Module
2//!
3//! Handles protocol communication with Mountain and other services.
4//! Implements the Spine protocol for extension host communication.
5
6pub mod SpineConnection;
7
8// Re-exports for convenience - use module prefix to avoid E0255 conflicts
9// Note: SpineConnection must be accessed via
10// SpineConnection::SpineConnectionImpl
11
12/// Protocol version
13pub const SPINE_PROTOCOL_VERSION:&str = "1.0.0";
14
15/// Default Mountain gRPC endpoint
16pub const DEFAULT_MOUNTAIN_ENDPOINT:&str = "127.0.0.1:50050";
17
18/// Default connection timeout in milliseconds
19pub const DEFAULT_CONNECTION_TIMEOUT_MS:u64 = 5000;
20
21/// Default heartbeat interval in seconds
22pub const DEFAULT_HEARTBEAT_INTERVAL_SEC:u64 = 30;
23
24/// Default message buffer size
25pub const DEFAULT_MESSAGE_BUFFER_SIZE:usize = 8192;
26
27/// Protocol configuration
28#[derive(Debug, Clone)]
29pub struct ProtocolConfig {
30	/// Protocol version
31	pub version:String,
32
33	/// Mountain endpoint
34	pub mountain_endpoint:String,
35
36	/// Connection timeout
37	pub connection_timeout_ms:u64,
38
39	/// Heartbeat interval
40	pub heartbeat_interval_sec:u64,
41
42	/// Message buffer size
43	pub message_buffer_size:usize,
44
45	/// Enable TLS
46	pub enable_tls:bool,
47
48	/// Enable compression
49	pub enable_compression:bool,
50}
51
52impl ProtocolConfig {
53	/// Create a new protocol configuration
54	pub fn new() -> Self {
55		Self {
56			version:SPINE_PROTOCOL_VERSION.to_string(),
57
58			mountain_endpoint:DEFAULT_MOUNTAIN_ENDPOINT.to_string(),
59
60			connection_timeout_ms:DEFAULT_CONNECTION_TIMEOUT_MS,
61
62			heartbeat_interval_sec:DEFAULT_HEARTBEAT_INTERVAL_SEC,
63
64			message_buffer_size:DEFAULT_MESSAGE_BUFFER_SIZE,
65
66			enable_tls:false,
67
68			enable_compression:false,
69		}
70	}
71
72	/// Set mountain endpoint
73	pub fn with_mountain_endpoint(mut self, endpoint:String) -> Self {
74		self.mountain_endpoint = endpoint;
75
76		self
77	}
78
79	/// Set connection timeout
80	pub fn with_connection_timeout(mut self, timeout_ms:u64) -> Self {
81		self.connection_timeout_ms = timeout_ms;
82
83		self
84	}
85
86	/// Set heartbeat interval
87	pub fn with_heartbeat_interval(mut self, interval_sec:u64) -> Self {
88		self.heartbeat_interval_sec = interval_sec;
89
90		self
91	}
92
93	/// Enable or disable TLS
94	pub fn with_tls(mut self, enable:bool) -> Self {
95		self.enable_tls = enable;
96
97		self
98	}
99
100	/// Enable or disable compression
101	pub fn with_compression(mut self, enable:bool) -> Self {
102		self.enable_compression = enable;
103
104		self
105	}
106}
107
108impl Default for ProtocolConfig {
109	fn default() -> Self { Self::new() }
110}
111
112/// Message types for Spine protocol
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
114pub enum MessageType {
115	/// Heartbeat message
116	Heartbeat = 0,
117
118	/// Registration message
119	Register = 1,
120
121	/// Unregistration message
122	Unregister = 2,
123
124	/// Event message
125	Event = 3,
126
127	/// Request message
128	Request = 4,
129
130	/// Response message
131	Response = 5,
132
133	/// Error message
134	Error = 6,
135}
136
137impl MessageType {
138	/// Convert to u32
139	pub fn as_u32(self) -> u32 { self as u32 }
140
141	/// Convert from u32
142	pub fn from_u32(value:u32) -> Option<Self> {
143		match value {
144			0 => Some(Self::Heartbeat),
145
146			1 => Some(Self::Register),
147
148			2 => Some(Self::Unregister),
149
150			3 => Some(Self::Event),
151
152			4 => Some(Self::Request),
153
154			5 => Some(Self::Response),
155
156			6 => Some(Self::Error),
157
158			_ => None,
159		}
160	}
161}
162
163/// Protocol error types
164#[derive(Debug, thiserror::Error)]
165pub enum ProtocolError {
166	/// Connection error
167	#[error("Connection error: {0}")]
168	ConnectionError(String),
169
170	/// Serialization error
171	#[error("Serialization error: {0}")]
172	SerializationError(String),
173
174	/// Deserialization error
175	#[error("Deserialization error: {0}")]
176	DeserializationError(String),
177
178	/// Invalid message error
179	#[error("Invalid message: {0}")]
180	InvalidMessage(String),
181
182	/// Timeout error
183	#[error("Timeout error")]
184	Timeout,
185
186	/// Protocol error
187	#[error("Protocol error: {0}")]
188	ProtocolError(String),
189}
190
191#[cfg(test)]
192mod tests {
193
194	use super::*;
195
196	#[test]
197	fn test_protocol_config_default() {
198		let config = ProtocolConfig::default();
199
200		assert_eq!(config.mountain_endpoint, DEFAULT_MOUNTAIN_ENDPOINT);
201
202		assert_eq!(config.connection_timeout_ms, DEFAULT_CONNECTION_TIMEOUT_MS);
203	}
204
205	#[test]
206	fn test_protocol_config_builder() {
207		let config = ProtocolConfig::default()
208			.with_mountain_endpoint("127.0.0.1:60000".to_string())
209			.with_connection_timeout(10000)
210			.with_heartbeat_interval(60);
211
212		assert_eq!(config.mountain_endpoint, "127.0.0.1:60000");
213
214		assert_eq!(config.connection_timeout_ms, 10000);
215
216		assert_eq!(config.heartbeat_interval_sec, 60);
217	}
218
219	#[test]
220	fn test_message_type_conversion() {
221		let msg_type = MessageType::Heartbeat;
222
223		assert_eq!(msg_type.as_u32(), 0);
224
225		let converted = MessageType::from_u32(0);
226
227		assert_eq!(converted, Some(MessageType::Heartbeat));
228
229		let invalid = MessageType::from_u32(999);
230
231		assert_eq!(invalid, None);
232	}
233}