use crate::error::OxCacheError;
pub fn validate_no_dangerous_chars(
input: &str,
dangerous_chars: &[char],
error_context: &str,
) -> crate::OxCacheResult<()> {
for c in input.chars() {
if dangerous_chars.contains(&c) {
let char_name = match c {
'\n' => "'\\n' (newline)".to_string(),
'\r' => "'\\r' (carriage return)".to_string(),
'\0' => "NUL".to_string(),
_ if c.is_control() => format!("U+{:04X} (control character)", c as u32),
_ => format!("U+{:04X}", c as u32),
};
return Err(OxCacheError::InvalidInput(format!(
"{} contains dangerous character {}",
error_context, char_name
)));
}
}
Ok(())
}
pub fn validate_not_empty(input: &str, error_context: &str) -> crate::OxCacheResult<()> {
if input.is_empty() {
return Err(OxCacheError::InvalidInput(format!("{} cannot be empty", error_context)));
}
Ok(())
}
pub fn validate_max_length(input: &str, max_length: usize, error_context: &str) -> crate::OxCacheResult<()> {
if input.len() > max_length {
return Err(OxCacheError::InvalidInput(format!(
"{} exceeds maximum length of {} (got {})",
error_context,
max_length,
input.len()
)));
}
Ok(())
}
pub mod redis {
pub const MAX_KEY_LENGTH: usize = 512 * 1024;
pub const DANGEROUS_CHARS: [char; 3] = ['\r', '\n', '\0'];
}
pub use redis::{DANGEROUS_CHARS, MAX_KEY_LENGTH};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_no_dangerous_chars_valid() {
let dangerous_chars = ['\r', '\n', '\0'];
let result = validate_no_dangerous_chars("safe_string", &dangerous_chars, "test");
assert!(result.is_ok());
}
#[test]
fn test_validate_no_dangerous_chars_invalid() {
let dangerous_chars = ['\r', '\n', '\0'];
let result = validate_no_dangerous_chars("unsafe\nstring", &dangerous_chars, "test");
assert!(result.is_err());
}
#[test]
fn test_validate_not_empty_valid() {
let result = validate_not_empty("non_empty", "test");
assert!(result.is_ok());
}
#[test]
fn test_validate_not_empty_invalid() {
let result = validate_not_empty("", "test");
assert!(result.is_err());
}
#[test]
fn test_validate_max_length_valid() {
let result = validate_max_length("short", 100, "test");
assert!(result.is_ok());
}
#[test]
fn test_validate_max_length_invalid() {
let result = validate_max_length(&"a".repeat(101), 100, "test");
assert!(result.is_err());
}
#[test]
fn test_redis_validate_key_valid() {
let result = validate_not_empty("my_key", "Redis key");
assert!(result.is_ok());
}
#[test]
fn test_redis_validate_key_empty() {
let result = validate_not_empty("", "Redis key");
assert!(result.is_err());
}
#[test]
fn test_redis_validate_key_dangerous_chars() {
let result = validate_no_dangerous_chars("key\nwith\nnewlines", &redis::DANGEROUS_CHARS, "Redis key");
assert!(result.is_err());
}
#[test]
fn test_redis_validate_key_too_long() {
let long_key = "a".repeat(redis::MAX_KEY_LENGTH + 1);
let result = validate_max_length(&long_key, redis::MAX_KEY_LENGTH, "Redis key");
assert!(result.is_err());
}
}