Skip to main content

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