alibabacloud-rum 0.1.0

Alibaba Cloud RUM SDK for native Rust applications.
Documentation
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct ParsedTraceParent {
    pub trace_id: String,
    pub span_id: String,
}

pub(crate) fn parse_traceparent(value: &str) -> Option<ParsedTraceParent> {
    let mut parts = value.split('-');
    let version = parts.next()?;
    let trace_id = parts.next()?;
    let span_id = parts.next()?;
    let flags = parts.next()?;
    if parts.next().is_some() || version.len() != 2 || flags.len() != 2 {
        return None;
    }
    if !is_lower_hex(version) || !is_lower_hex(flags) || version == "ff" {
        return None;
    }
    if trace_id.len() != 32 || span_id.len() != 16 {
        return None;
    }
    if trace_id.chars().all(|c| c == '0') || span_id.chars().all(|c| c == '0') {
        return None;
    }
    if !is_lower_hex(trace_id) || !is_lower_hex(span_id) {
        return None;
    }
    Some(ParsedTraceParent {
        trace_id: trace_id.to_string(),
        span_id: span_id.to_string(),
    })
}

fn is_lower_hex(value: &str) -> bool {
    value
        .bytes()
        .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_valid_traceparent() {
        let parsed =
            parse_traceparent("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01").unwrap();
        assert_eq!(parsed.trace_id, "4bf92f3577b34da6a3ce929d0e0e4736");
        assert_eq!(parsed.span_id, "00f067aa0ba902b7");
    }

    #[test]
    fn rejects_forbidden_ff_version() {
        assert!(
            parse_traceparent("ff-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01").is_none()
        );
    }

    #[test]
    fn rejects_non_hex_version_and_flags() {
        assert!(
            parse_traceparent("0g-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01").is_none()
        );
        assert!(
            parse_traceparent("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-zz").is_none()
        );
    }

    #[test]
    fn rejects_uppercase_hex_fields() {
        assert!(
            parse_traceparent("00-4BF92F3577B34DA6A3CE929D0E0E4736-00f067aa0ba902b7-01").is_none()
        );
    }
}