use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::Result;
use crate::error::OdinError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OdinConfig {
pub node_id: String,
pub network_endpoint: String,
pub token: Option<String>,
pub timeout: Duration,
pub max_connections: usize,
pub heartbeat_interval: Duration,
pub max_retries: u32,
pub debug: bool,
pub performance_monitoring: bool,
pub max_message_size: usize,
pub buffer_size: usize,
}
impl Default for OdinConfig {
fn default() -> Self {
Self {
node_id: uuid::Uuid::new_v4().to_string(),
network_endpoint: "ws://localhost:8080".to_string(),
token: None,
timeout: crate::defaults::TIMEOUT,
max_connections: crate::defaults::MAX_CONNECTIONS,
heartbeat_interval: crate::defaults::HEARTBEAT_INTERVAL,
max_retries: crate::defaults::MAX_RETRIES,
debug: false,
performance_monitoring: true,
max_message_size: crate::defaults::MAX_MESSAGE_SIZE,
buffer_size: crate::defaults::BUFFER_SIZE,
}
}
}
impl OdinConfig {
pub fn builder() -> OdinConfigBuilder {
OdinConfigBuilder::new()
}
pub fn validate(&self) -> Result<()> {
if self.node_id.is_empty() {
return Err(OdinError::Configuration("Node ID cannot be empty".to_string()));
}
if self.network_endpoint.is_empty() {
return Err(OdinError::Configuration("Network endpoint cannot be empty".to_string()));
}
if self.max_connections == 0 {
return Err(OdinError::Configuration("Max connections must be greater than 0".to_string()));
}
if self.max_message_size == 0 {
return Err(OdinError::Configuration("Max message size must be greater than 0".to_string()));
}
Ok(())
}
}
#[derive(Debug, Default)]
pub struct OdinConfigBuilder {
node_id: Option<String>,
network_endpoint: Option<String>,
token: Option<String>,
timeout: Option<Duration>,
max_connections: Option<usize>,
heartbeat_interval: Option<Duration>,
max_retries: Option<u32>,
debug: Option<bool>,
performance_monitoring: Option<bool>,
max_message_size: Option<usize>,
buffer_size: Option<usize>,
}
impl OdinConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn node_id<S: Into<String>>(mut self, node_id: S) -> Self {
self.node_id = Some(node_id.into());
self
}
pub fn network_endpoint<S: Into<String>>(mut self, endpoint: S) -> Self {
self.network_endpoint = Some(endpoint.into());
self
}
pub fn token<S: Into<String>>(mut self, token: S) -> Self {
self.token = Some(token.into());
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn max_connections(mut self, max_connections: usize) -> Self {
self.max_connections = Some(max_connections);
self
}
pub fn heartbeat_interval(mut self, interval: Duration) -> Self {
self.heartbeat_interval = Some(interval);
self
}
pub fn max_retries(mut self, max_retries: u32) -> Self {
self.max_retries = Some(max_retries);
self
}
pub fn debug(mut self, debug: bool) -> Self {
self.debug = Some(debug);
self
}
pub fn performance_monitoring(mut self, enabled: bool) -> Self {
self.performance_monitoring = Some(enabled);
self
}
pub fn max_message_size(mut self, size: usize) -> Self {
self.max_message_size = Some(size);
self
}
pub fn buffer_size(mut self, size: usize) -> Self {
self.buffer_size = Some(size);
self
}
pub fn build(self) -> Result<OdinConfig> {
let mut config = OdinConfig::default();
if let Some(node_id) = self.node_id {
config.node_id = node_id;
}
if let Some(endpoint) = self.network_endpoint {
config.network_endpoint = endpoint;
}
config.token = self.token;
if let Some(timeout) = self.timeout {
config.timeout = timeout;
}
if let Some(max_connections) = self.max_connections {
config.max_connections = max_connections;
}
if let Some(interval) = self.heartbeat_interval {
config.heartbeat_interval = interval;
}
if let Some(max_retries) = self.max_retries {
config.max_retries = max_retries;
}
if let Some(debug) = self.debug {
config.debug = debug;
}
if let Some(monitoring) = self.performance_monitoring {
config.performance_monitoring = monitoring;
}
if let Some(size) = self.max_message_size {
config.max_message_size = size;
}
if let Some(size) = self.buffer_size {
config.buffer_size = size;
}
config.validate()?;
Ok(config)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_default_config() {
let config = OdinConfig::default();
assert!(!config.node_id.is_empty());
assert_eq!(config.network_endpoint, "ws://localhost:8080");
assert!(!config.debug);
assert!(config.performance_monitoring);
}
#[test]
fn test_config_builder() {
let config = OdinConfig::builder()
.node_id("test-node")
.network_endpoint("wss://example.com:9000")
.timeout(Duration::from_secs(60))
.max_connections(200)
.debug(true)
.build()
.unwrap();
assert_eq!(config.node_id, "test-node");
assert_eq!(config.network_endpoint, "wss://example.com:9000");
assert_eq!(config.timeout, Duration::from_secs(60));
assert_eq!(config.max_connections, 200);
assert!(config.debug);
}
#[test]
fn test_config_validation() {
let result = OdinConfig::builder()
.node_id("")
.build();
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), OdinError::Configuration(_)));
}
}