use anyhow::{Result, bail};
pub struct ExpverHandler;
impl ExpverHandler {
pub fn validate_and_canonicalize(
value: &str,
default: Option<&str>,
field_name: &str,
) -> Result<String> {
if value.is_empty() {
if let Some(default_val) = default {
let canonicalized_default = Self::canonicalize_expver(default_val);
tracing::debug!(
field_name = field_name,
default_value = default_val,
canonical_value = %canonicalized_default,
"Using default experiment version"
);
return Ok(canonicalized_default);
} else {
bail!("Field '{}' cannot be empty", field_name);
}
}
let canonicalized = Self::canonicalize_expver(value);
tracing::debug!(
field_name = field_name,
input_value = value,
canonical_value = %canonicalized,
value_type = if value.parse::<u32>().is_ok() { "numeric" } else { "string" },
"Experiment version successfully validated and canonicalized"
);
Ok(canonicalized)
}
fn canonicalize_expver(value: &str) -> String {
if let Ok(num) = value.parse::<u32>() {
format!("{:04}", num)
} else {
value.to_lowercase()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_numeric_expver_single_digit() {
let result = ExpverHandler::validate_and_canonicalize("1", None, "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "0001");
}
#[test]
fn test_numeric_expver_multiple_digits() {
let result = ExpverHandler::validate_and_canonicalize("42", None, "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "0042");
}
#[test]
fn test_numeric_expver_four_digits() {
let result = ExpverHandler::validate_and_canonicalize("9999", None, "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "9999");
}
#[test]
fn test_string_expver_uppercase() {
let result = ExpverHandler::validate_and_canonicalize("PROD", None, "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "prod");
}
#[test]
fn test_string_expver_mixed_case() {
let result = ExpverHandler::validate_and_canonicalize("Test", None, "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "test");
}
#[test]
fn test_empty_with_numeric_default() {
let result = ExpverHandler::validate_and_canonicalize("", Some("42"), "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "0042");
}
#[test]
fn test_empty_with_string_default() {
let result = ExpverHandler::validate_and_canonicalize("", Some("PROD"), "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "prod");
}
#[test]
fn test_empty_without_default() {
let result = ExpverHandler::validate_and_canonicalize("", None, "expver");
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("cannot be empty"));
}
#[test]
fn test_alphanumeric_string() {
let result = ExpverHandler::validate_and_canonicalize("dev-v2.1", None, "expver");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "dev-v2.1");
}
}