use super::Signal;
#[derive(Debug, Clone)]
pub enum ValidationResult {
Valid,
Invalid(Vec<String>),
}
impl ValidationResult {
pub fn is_valid(&self) -> bool {
matches!(self, Self::Valid)
}
pub fn errors(&self) -> &[String] {
match self {
Self::Invalid(errors) => errors,
Self::Valid => &[],
}
}
}
pub struct SignalValidator {
max_payload_size: usize,
allowed_types: Option<Vec<String>>,
}
impl SignalValidator {
pub fn new() -> Self {
Self {
max_payload_size: 1024 * 1024, allowed_types: None,
}
}
pub fn with_max_payload_size(mut self, size: usize) -> Self {
self.max_payload_size = size;
self
}
pub fn with_allowed_types(mut self, types: Vec<String>) -> Self {
self.allowed_types = Some(types);
self
}
pub fn validate(&self, signal: &Signal) -> ValidationResult {
let mut errors = Vec::new();
let payload_str = signal.payload.to_string();
if payload_str.len() > self.max_payload_size {
errors.push(format!(
"Payload exceeds maximum size of {} bytes",
self.max_payload_size
));
}
if let Some(ref allowed) = self.allowed_types {
if !allowed.contains(&signal.signal_type) {
errors.push(format!(
"Signal type '{}' not in allowed types",
signal.signal_type
));
}
}
if signal.source.is_empty() {
errors.push("Signal source cannot be empty".to_string());
}
if errors.is_empty() {
ValidationResult::Valid
} else {
ValidationResult::Invalid(errors)
}
}
}
impl Default for SignalValidator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid_signal() {
let validator = SignalValidator::new();
let signal = Signal::new("test", serde_json::json!({"key": "value"}), "source");
assert!(validator.validate(&signal).is_valid());
}
#[test]
fn test_empty_source() {
let validator = SignalValidator::new();
let mut signal = Signal::new("test", serde_json::json!({}), "source");
signal.source = String::new();
let result = validator.validate(&signal);
assert!(!result.is_valid());
assert!(result.errors()[0].contains("source"));
}
#[test]
fn test_disallowed_type() {
let validator = SignalValidator::new().with_allowed_types(vec!["allowed".to_string()]);
let signal = Signal::new("disallowed", serde_json::json!({}), "source");
let result = validator.validate(&signal);
assert!(!result.is_valid());
}
}