use crate::trace::propagation::context::PropagationContext;
use base64::prelude::*;
pub fn decode_propagation(header_value: &str) -> crate::Result<PropagationContext> {
let pieces: Vec<&str> = header_value.split('-').collect();
if pieces.len() != 8 {
return Err(crate::Error::DecodePropagation(
"failed to parse propagation context: it must have 8 properties.",
));
}
let do_sample = try_parse_sample_status(pieces[0])?;
let parent_trace_id = b64_encoded_into_string(pieces[1])?;
let parent_trace_segment_id = b64_encoded_into_string(pieces[2])?;
let parent_span_id: i32 = try_parse_parent_span_id(pieces[3])?;
let parent_service = b64_encoded_into_string(pieces[4])?;
let parent_service_instance = b64_encoded_into_string(pieces[5])?;
let destination_endpoint = b64_encoded_into_string(pieces[6])?;
let destination_address = b64_encoded_into_string(pieces[7])?;
let context = PropagationContext::new(
do_sample,
parent_trace_id,
parent_trace_segment_id,
parent_span_id,
parent_service,
parent_service_instance,
destination_endpoint,
destination_address,
);
Ok(context)
}
fn try_parse_parent_span_id(id: &str) -> crate::Result<i32> {
if let Ok(result) = id.parse::<i32>() {
Ok(result)
} else {
Err(crate::Error::DecodePropagation(
"failed to parse span id from parent.",
))
}
}
fn try_parse_sample_status(status: &str) -> crate::Result<bool> {
if status == "0" {
Ok(false)
} else if status == "1" {
Ok(true)
} else {
Err(crate::Error::DecodePropagation(
"failed to parse sample status.",
))
}
}
fn b64_encoded_into_string(enc: &str) -> crate::Result<String> {
if let Ok(result) = BASE64_STANDARD.decode(enc) {
if let Ok(decoded_str) = String::from_utf8(result) {
return Ok(decoded_str);
}
}
Err(crate::Error::DecodePropagation("failed to decode value."))
}