use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq)]
pub enum OtelIdError {
#[error("trace_id must be exactly 32 lowercase hexadecimal characters, got: {0}")]
InvalidTraceId(String),
#[error("span_id must be exactly 16 lowercase hexadecimal characters, got: {0}")]
InvalidSpanId(String),
}
pub fn validate_trace_id(trace_id: &str) -> Result<(), OtelIdError> {
if trace_id.len() != 32 {
return Err(OtelIdError::InvalidTraceId(trace_id.to_string()));
}
if !trace_id
.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase())
{
return Err(OtelIdError::InvalidTraceId(trace_id.to_string()));
}
Ok(())
}
pub fn validate_span_id(span_id: &str) -> Result<(), OtelIdError> {
if span_id.len() != 16 {
return Err(OtelIdError::InvalidSpanId(span_id.to_string()));
}
if !span_id
.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase())
{
return Err(OtelIdError::InvalidSpanId(span_id.to_string()));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_trace_id_valid() {
assert!(validate_trace_id("4f9b7a7a9b0a4a9e8b0a4a9e8b0a4a9e").is_ok());
assert!(validate_trace_id("00000000000000000000000000000000").is_ok());
assert!(validate_trace_id("ffffffffffffffffffffffffffffffff").is_ok());
}
#[test]
fn test_validate_trace_id_invalid_length() {
assert!(validate_trace_id("4f9b7a7a9b0a4a9e8b0a4a9e8b0a4a").is_err());
assert!(validate_trace_id("4f9b7a7a9b0a4a9e8b0a4a9e8b0a4a9e8").is_err());
}
#[test]
fn test_validate_trace_id_invalid_case() {
assert!(validate_trace_id("4f9b7a7a9b0a4a9e8b0a4a9e8b0a4a9E").is_err());
assert!(validate_trace_id("4F9B7A7A9B0A4A9E8B0A4A9E8B0A4A9E").is_err());
}
#[test]
fn test_validate_trace_id_invalid_chars() {
assert!(validate_trace_id("4f9b7a7a9b0a4a9e8b0a4a9e8b0a4a9g").is_err());
assert!(validate_trace_id("4f9b7a7a9b0a4a9e8b0a4a9e8b0a4a9-").is_err());
}
#[test]
fn test_validate_span_id_valid() {
assert!(validate_span_id("d2b8c1e4f7a12345").is_ok());
assert!(validate_span_id("0000000000000000").is_ok());
assert!(validate_span_id("ffffffffffffffff").is_ok());
}
#[test]
fn test_validate_span_id_invalid_length() {
assert!(validate_span_id("d2b8c1e4f7a1234").is_err());
assert!(validate_span_id("d2b8c1e4f7a123456").is_err());
}
#[test]
fn test_validate_span_id_invalid_case() {
assert!(validate_span_id("d2b8c1e4f7a1234F").is_err());
assert!(validate_span_id("D2B8C1E4F7A12345").is_err());
}
#[test]
fn test_validate_span_id_invalid_chars() {
assert!(validate_span_id("d2b8c1e4f7a1234g").is_err());
assert!(validate_span_id("d2b8c1e4f7a1234-").is_err());
}
}