libdd_trace_utils/msgpack_decoder/decode/
span_event.rs

1// Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::msgpack_decoder::decode::error::DecodeError;
5use crate::msgpack_decoder::decode::number::read_number_slice;
6use crate::msgpack_decoder::decode::string::{handle_null_marker, read_string_ref};
7use crate::span::{AttributeAnyValueSlice, AttributeArrayValueSlice, SpanEventSlice};
8use std::collections::HashMap;
9use std::str::FromStr;
10
11/// Reads a slice of bytes and decodes it into a vector of `SpanEvent` objects.
12///
13/// # Arguments
14///
15/// * `buf` - A mutable reference to a slice of bytes containing the encoded data.
16///
17/// # Returns
18///
19/// * `Ok(Vec<SpanEvent>)` - A vector of decoded `SpanEvent` objects if successful.
20/// * `Err(DecodeError)` - An error if the decoding process fails.
21///
22/// # Errors
23///
24/// This function will return an error if:
25/// - The marker for the array length cannot be read.
26/// - Any `SpanEvent` cannot be decoded.
27pub(crate) fn read_span_events<'a>(
28    buf: &mut &'a [u8],
29) -> Result<Vec<SpanEventSlice<'a>>, DecodeError> {
30    if handle_null_marker(buf) {
31        return Ok(Vec::default());
32    }
33
34    let len = rmp::decode::read_array_len(buf).map_err(|_| {
35        DecodeError::InvalidType("Unable to get array len for span events".to_owned())
36    })?;
37
38    let mut vec: Vec<SpanEventSlice> = Vec::with_capacity(len as usize);
39    for _ in 0..len {
40        vec.push(decode_span_event(buf)?);
41    }
42    Ok(vec)
43}
44#[derive(Debug, PartialEq)]
45enum SpanEventKey {
46    TimeUnixNano,
47    Name,
48    Attributes,
49}
50
51impl FromStr for SpanEventKey {
52    type Err = DecodeError;
53
54    fn from_str(s: &str) -> Result<Self, Self::Err> {
55        match s {
56            "time_unix_nano" => Ok(SpanEventKey::TimeUnixNano),
57            "name" => Ok(SpanEventKey::Name),
58            "attributes" => Ok(SpanEventKey::Attributes),
59            _ => Err(DecodeError::InvalidFormat(
60                format!("Invalid span event key: {s}").to_owned(),
61            )),
62        }
63    }
64}
65
66fn decode_span_event<'a>(buf: &mut &'a [u8]) -> Result<SpanEventSlice<'a>, DecodeError> {
67    let mut event = SpanEventSlice::default();
68    let event_size = rmp::decode::read_map_len(buf)
69        .map_err(|_| DecodeError::InvalidType("Unable to get map len for event size".to_owned()))?;
70
71    for _ in 0..event_size {
72        match read_string_ref(buf)?.parse::<SpanEventKey>()? {
73            SpanEventKey::TimeUnixNano => event.time_unix_nano = read_number_slice(buf)?,
74            SpanEventKey::Name => event.name = read_string_ref(buf)?,
75            SpanEventKey::Attributes => event.attributes = read_attributes_map(buf)?,
76        }
77    }
78
79    Ok(event)
80}
81
82fn read_attributes_map<'a>(
83    buf: &mut &'a [u8],
84) -> Result<HashMap<&'a str, AttributeAnyValueSlice<'a>>, DecodeError> {
85    let len = rmp::decode::read_map_len(buf)
86        .map_err(|_| DecodeError::InvalidType("Unable to get map len for attributes".to_owned()))?;
87
88    #[allow(clippy::expect_used)]
89    let mut map = HashMap::with_capacity(len.try_into().expect("Unable to cast map len to usize"));
90    for _ in 0..len {
91        let key = read_string_ref(buf)?;
92        let value = decode_attribute_any(buf)?;
93        map.insert(key, value);
94    }
95
96    Ok(map)
97}
98
99#[derive(Debug, PartialEq)]
100enum AttributeAnyKey {
101    Type,
102    SingleValue(AttributeArrayKey),
103    ArrayValue,
104}
105
106impl FromStr for AttributeAnyKey {
107    type Err = DecodeError;
108
109    fn from_str(s: &str) -> Result<Self, Self::Err> {
110        match s {
111            "type" => Ok(AttributeAnyKey::Type),
112            "array_value" => Ok(AttributeAnyKey::ArrayValue),
113            s => {
114                let r = AttributeArrayKey::from_str(s);
115                match r {
116                    Ok(key) => Ok(AttributeAnyKey::SingleValue(key)),
117                    Err(e) => Err(e),
118                }
119            }
120        }
121    }
122}
123
124fn decode_attribute_any<'a>(buf: &mut &'a [u8]) -> Result<AttributeAnyValueSlice<'a>, DecodeError> {
125    let mut attribute: Option<AttributeAnyValueSlice> = None;
126    let attribute_size = rmp::decode::read_map_len(buf).map_err(|_| {
127        DecodeError::InvalidType("Unable to get map len for attribute size".to_owned())
128    })?;
129
130    if attribute_size != 2 {
131        return Err(DecodeError::InvalidFormat(
132            "Invalid number of field for an attribute".to_owned(),
133        ));
134    }
135    let mut attribute_type: Option<u8> = None;
136
137    for _ in 0..attribute_size {
138        match read_string_ref(buf)?.parse::<AttributeAnyKey>()? {
139            AttributeAnyKey::Type => attribute_type = Some(read_number_slice(buf)?),
140            AttributeAnyKey::SingleValue(key) => {
141                attribute = Some(AttributeAnyValueSlice::SingleValue(get_attribute_from_key(
142                    buf, key,
143                )?))
144            }
145            AttributeAnyKey::ArrayValue => {
146                attribute = Some(AttributeAnyValueSlice::Array(read_attributes_array(buf)?))
147            }
148        }
149    }
150
151    if let Some(value) = attribute {
152        if let Some(attribute_type) = attribute_type {
153            let value_type: u8 = (&value).into();
154            if attribute_type == value_type {
155                Ok(value)
156            } else {
157                Err(DecodeError::InvalidFormat(
158                    "No type for attribute".to_owned(),
159                ))
160            }
161        } else {
162            Err(DecodeError::InvalidType(
163                "Type mismatch for attribute".to_owned(),
164            ))
165        }
166    } else {
167        Err(DecodeError::InvalidFormat("Invalid attribute".to_owned()))
168    }
169}
170
171fn read_attributes_array<'a>(
172    buf: &mut &'a [u8],
173) -> Result<Vec<AttributeArrayValueSlice<'a>>, DecodeError> {
174    if handle_null_marker(buf) {
175        return Ok(Vec::default());
176    }
177
178    let map_len = rmp::decode::read_map_len(buf).map_err(|_| {
179        DecodeError::InvalidType(
180            "Unable to get map len for event attributes array_value object".to_owned(),
181        )
182    })?;
183
184    if map_len != 1 {
185        return Err(DecodeError::InvalidFormat(
186            "event attributes array_value object should only have 'values' field".to_owned(),
187        ));
188    }
189
190    let key = read_string_ref(buf)?;
191    if key != "values" {
192        return Err(DecodeError::InvalidFormat(
193            "Expected 'values' field in event attributes array_value object".to_owned(),
194        ));
195    }
196
197    let len = rmp::decode::read_array_len(buf).map_err(|_| {
198        DecodeError::InvalidType(
199            "Unable to get array len for event attributes values field".to_owned(),
200        )
201    })?;
202
203    let mut vec: Vec<AttributeArrayValueSlice> = Vec::with_capacity(len as usize);
204    if len > 0 {
205        let first = decode_attribute_array(buf, None)?;
206        let array_type = (&first).into();
207        vec.push(first);
208        for _ in 1..len {
209            vec.push(decode_attribute_array(buf, Some(array_type))?);
210        }
211    }
212    Ok(vec)
213}
214
215#[derive(Debug, PartialEq)]
216enum AttributeArrayKey {
217    Type,
218    StringValue,
219    BoolValue,
220    IntValue,
221    DoubleValue,
222}
223
224impl FromStr for AttributeArrayKey {
225    type Err = DecodeError;
226
227    fn from_str(s: &str) -> Result<Self, Self::Err> {
228        match s {
229            "type" => Ok(AttributeArrayKey::Type),
230            "string_value" => Ok(AttributeArrayKey::StringValue),
231            "bool_value" => Ok(AttributeArrayKey::BoolValue),
232            "int_value" => Ok(AttributeArrayKey::IntValue),
233            "double_value" => Ok(AttributeArrayKey::DoubleValue),
234            _ => Err(DecodeError::InvalidFormat(
235                format!("Invalid attribute key: {s}").to_owned(),
236            )),
237        }
238    }
239}
240
241fn get_attribute_from_key<'a>(
242    buf: &mut &'a [u8],
243    key: AttributeArrayKey,
244) -> Result<AttributeArrayValueSlice<'a>, DecodeError> {
245    match key {
246        AttributeArrayKey::StringValue => {
247            Ok(AttributeArrayValueSlice::String(read_string_ref(buf)?))
248        }
249        AttributeArrayKey::BoolValue => {
250            let boolean = rmp::decode::read_bool(buf);
251            if let Ok(value) = boolean {
252                match value {
253                    true => Ok(AttributeArrayValueSlice::Boolean(true)),
254                    false => Ok(AttributeArrayValueSlice::Boolean(false)),
255                }
256            } else {
257                Err(DecodeError::InvalidType("Invalid boolean field".to_owned()))
258            }
259        }
260        AttributeArrayKey::IntValue => {
261            Ok(AttributeArrayValueSlice::Integer(read_number_slice(buf)?))
262        }
263        AttributeArrayKey::DoubleValue => {
264            Ok(AttributeArrayValueSlice::Double(read_number_slice(buf)?))
265        }
266        _ => Err(DecodeError::InvalidFormat("Invalid attribute".to_owned())),
267    }
268}
269
270fn decode_attribute_array<'a>(
271    buf: &mut &'a [u8],
272    array_type: Option<u8>,
273) -> Result<AttributeArrayValueSlice<'a>, DecodeError> {
274    let mut attribute: Option<AttributeArrayValueSlice> = None;
275    let attribute_size = rmp::decode::read_map_len(buf).map_err(|_| {
276        DecodeError::InvalidType("Unable to get map len for attribute size".to_owned())
277    })?;
278
279    if attribute_size != 2 {
280        return Err(DecodeError::InvalidFormat(
281            "Invalid number of field for an attribute".to_owned(),
282        ));
283    }
284    let mut attribute_type: Option<u8> = None;
285
286    for _ in 0..attribute_size {
287        match read_string_ref(buf)?.parse::<AttributeArrayKey>()? {
288            AttributeArrayKey::Type => attribute_type = Some(read_number_slice(buf)?),
289            key => attribute = Some(get_attribute_from_key(buf, key)?),
290        }
291    }
292
293    if let Some(value) = attribute {
294        if let Some(attribute_type) = attribute_type {
295            let value_type: u8 = (&value).into();
296            if attribute_type == value_type {
297                if let Some(array_type) = array_type {
298                    if array_type != attribute_type {
299                        return Err(DecodeError::InvalidType(
300                            "Array must have same type element".to_owned(),
301                        ));
302                    }
303                }
304                Ok(value)
305            } else {
306                Err(DecodeError::InvalidFormat(
307                    "No type for attribute".to_owned(),
308                ))
309            }
310        } else {
311            Err(DecodeError::InvalidType(
312                "Type mismatch for attribute".to_owned(),
313            ))
314        }
315    } else {
316        Err(DecodeError::InvalidFormat("Invalid attribute".to_owned()))
317    }
318}
319
320#[cfg(test)]
321mod tests {
322    use super::AttributeAnyKey;
323    use super::AttributeArrayKey;
324    use super::SpanEventKey;
325    use crate::msgpack_decoder::decode::error::DecodeError;
326    use std::str::FromStr;
327
328    #[test]
329    fn test_span_event_key_from_str() {
330        // Valid cases
331        assert_eq!(
332            SpanEventKey::from_str("time_unix_nano").unwrap(),
333            SpanEventKey::TimeUnixNano
334        );
335        assert_eq!(SpanEventKey::from_str("name").unwrap(), SpanEventKey::Name);
336        assert_eq!(
337            SpanEventKey::from_str("attributes").unwrap(),
338            SpanEventKey::Attributes
339        );
340
341        // Invalid case
342        assert!(matches!(
343            SpanEventKey::from_str("invalid_key"),
344            Err(DecodeError::InvalidFormat(_))
345        ));
346    }
347
348    #[test]
349    fn test_attribute_any_key_from_str() {
350        // Valid cases
351        assert_eq!(
352            AttributeAnyKey::from_str("type").unwrap(),
353            AttributeAnyKey::Type
354        );
355        assert_eq!(
356            AttributeAnyKey::from_str("string_value").unwrap(),
357            AttributeAnyKey::SingleValue(AttributeArrayKey::StringValue)
358        );
359        assert_eq!(
360            AttributeAnyKey::from_str("bool_value").unwrap(),
361            AttributeAnyKey::SingleValue(AttributeArrayKey::BoolValue)
362        );
363        assert_eq!(
364            AttributeAnyKey::from_str("int_value").unwrap(),
365            AttributeAnyKey::SingleValue(AttributeArrayKey::IntValue)
366        );
367        assert_eq!(
368            AttributeAnyKey::from_str("double_value").unwrap(),
369            AttributeAnyKey::SingleValue(AttributeArrayKey::DoubleValue)
370        );
371        assert_eq!(
372            AttributeAnyKey::from_str("array_value").unwrap(),
373            AttributeAnyKey::ArrayValue
374        );
375
376        // Invalid case
377        assert!(matches!(
378            AttributeAnyKey::from_str("invalid_key"),
379            Err(DecodeError::InvalidFormat(_))
380        ));
381    }
382
383    #[test]
384    fn test_attribute_array_key_from_str() {
385        // Valid cases
386        assert_eq!(
387            AttributeArrayKey::from_str("type").unwrap(),
388            AttributeArrayKey::Type
389        );
390        assert_eq!(
391            AttributeArrayKey::from_str("string_value").unwrap(),
392            AttributeArrayKey::StringValue
393        );
394        assert_eq!(
395            AttributeArrayKey::from_str("bool_value").unwrap(),
396            AttributeArrayKey::BoolValue
397        );
398        assert_eq!(
399            AttributeArrayKey::from_str("int_value").unwrap(),
400            AttributeArrayKey::IntValue
401        );
402        assert_eq!(
403            AttributeArrayKey::from_str("double_value").unwrap(),
404            AttributeArrayKey::DoubleValue
405        );
406
407        // Invalid case
408        assert!(matches!(
409            AttributeArrayKey::from_str("invalid_key"),
410            Err(DecodeError::InvalidFormat(_))
411        ));
412    }
413}