agent_kernel/
validation.rs

1//! Input validation for MXP messages.
2
3use thiserror::Error;
4
5/// Configuration for message validation.
6#[derive(Debug, Clone)]
7pub struct ValidationConfig {
8    /// Maximum allowed message payload size in bytes.
9    pub max_payload_size: usize,
10    /// Maximum allowed message header size in bytes.
11    pub max_header_size: usize,
12}
13
14impl ValidationConfig {
15    /// Create a new validation configuration.
16    pub fn new(max_payload_size: usize, max_header_size: usize) -> Self {
17        Self {
18            max_payload_size,
19            max_header_size,
20        }
21    }
22}
23
24impl Default for ValidationConfig {
25    fn default() -> Self {
26        Self {
27            max_payload_size: 10 * 1024 * 1024, // 10 MB
28            max_header_size: 64 * 1024,         // 64 KB
29        }
30    }
31}
32
33/// Errors that can occur during message validation.
34#[derive(Debug, Error, PartialEq, Eq)]
35pub enum ValidationError {
36    /// Message payload exceeds the configured size limit.
37    #[error("message payload size {size} exceeds limit {limit}")]
38    PayloadTooLarge {
39        /// The actual payload size.
40        size: usize,
41        /// The configured limit.
42        limit: usize,
43    },
44
45    /// Message header exceeds the configured size limit.
46    #[error("message header size {size} exceeds limit {limit}")]
47    HeaderTooLarge {
48        /// The actual header size.
49        size: usize,
50        /// The configured limit.
51        limit: usize,
52    },
53}
54
55/// Result alias for validation operations.
56pub type ValidationResult<T = ()> = Result<T, ValidationError>;
57
58/// Validates an MXP message against configured limits.
59pub fn validate_message(
60    payload_size: usize,
61    header_size: usize,
62    config: &ValidationConfig,
63) -> ValidationResult {
64    if payload_size > config.max_payload_size {
65        return Err(ValidationError::PayloadTooLarge {
66            size: payload_size,
67            limit: config.max_payload_size,
68        });
69    }
70
71    if header_size > config.max_header_size {
72        return Err(ValidationError::HeaderTooLarge {
73            size: header_size,
74            limit: config.max_header_size,
75        });
76    }
77
78    Ok(())
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn validation_config_default() {
87        let config = ValidationConfig::default();
88        assert_eq!(config.max_payload_size, 10 * 1024 * 1024);
89        assert_eq!(config.max_header_size, 64 * 1024);
90    }
91
92    #[test]
93    fn validate_message_within_limits() {
94        let config = ValidationConfig::new(1000, 100);
95        let result = validate_message(500, 50, &config);
96        assert!(result.is_ok());
97    }
98
99    #[test]
100    fn validate_message_payload_too_large() {
101        let config = ValidationConfig::new(1000, 100);
102        let result = validate_message(1500, 50, &config);
103        assert!(matches!(
104            result,
105            Err(ValidationError::PayloadTooLarge {
106                size: 1500,
107                limit: 1000
108            })
109        ));
110    }
111
112    #[test]
113    fn validate_message_header_too_large() {
114        let config = ValidationConfig::new(1000, 100);
115        let result = validate_message(500, 150, &config);
116        assert!(matches!(
117            result,
118            Err(ValidationError::HeaderTooLarge {
119                size: 150,
120                limit: 100
121            })
122        ));
123    }
124
125    #[test]
126    fn validate_message_at_exact_limits() {
127        let config = ValidationConfig::new(1000, 100);
128        let result = validate_message(1000, 100, &config);
129        assert!(result.is_ok());
130    }
131
132    #[test]
133    fn validate_message_just_over_payload_limit() {
134        let config = ValidationConfig::new(1000, 100);
135        let result = validate_message(1001, 100, &config);
136        assert!(matches!(
137            result,
138            Err(ValidationError::PayloadTooLarge {
139                size: 1001,
140                limit: 1000
141            })
142        ));
143    }
144
145    #[test]
146    fn validate_message_just_over_header_limit() {
147        let config = ValidationConfig::new(1000, 100);
148        let result = validate_message(1000, 101, &config);
149        assert!(matches!(
150            result,
151            Err(ValidationError::HeaderTooLarge {
152                size: 101,
153                limit: 100
154            })
155        ));
156    }
157}