Skip to main content

libdd_trace_utils/msgpack_decoder/decode/
map.rs

1// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::msgpack_decoder::decode::{buffer::Buffer, error::DecodeError};
5use crate::span::vec_map::VecMap;
6use crate::span::DeserializableTraceData;
7use rmp::{decode, decode::RmpRead, Marker};
8use std::collections::HashMap;
9
10/// Reads a map from the buffer and returns it as a `HashMap`.
11///
12/// This function is generic over the key and value types of the map, and it uses a provided
13/// function to read key-value pairs from the buffer.
14///
15/// # Arguments
16///
17/// * `len` - The number of key-value pairs to read from the buffer.
18/// * `buf` - A reference to the slice containing the encoded map data.
19/// * `read_pair` - A function that reads a key-value pair from the buffer and returns it as a
20///   `Result<(K, V), DecodeError>`.
21///
22/// # Returns
23///
24/// * `Ok(HashMap<K, V>)` - A `HashMap` containing the decoded key-value pairs if successful.
25/// * `Err(DecodeError)` - An error if the decoding process fails.
26///
27/// # Errors
28///
29/// This function will return an error if:
30/// - The `read_pair` function returns an error while reading a key-value pair.
31///
32/// # Type Parameters
33///
34/// * `K` - The type of the keys in the map. Must implement `std::hash::Hash` and `Eq`.
35/// * `V` - The type of the values in the map.
36/// * `F` - The type of the function used to read key-value pairs from the buffer.
37#[inline]
38pub fn read_map<K, V, F, B>(
39    len: usize,
40    buf: &mut B,
41    read_pair: F,
42) -> Result<HashMap<K, V>, DecodeError>
43where
44    K: std::hash::Hash + Eq,
45    F: Fn(&mut B) -> Result<(K, V), DecodeError>,
46{
47    let mut map = HashMap::with_capacity(len);
48    for _ in 0..len {
49        let (k, v) = read_pair(buf)?;
50        map.insert(k, v);
51    }
52    Ok(map)
53}
54
55/// Reads a map from the buffer and returns it as a `VecMap<K, V>`.
56///
57/// Like `read_map` but returns pairs in a VecMap instead of HashMap for better
58/// cache locality when iteration order doesn't matter.
59#[inline]
60pub fn read_map_vec<K, V, F, B>(
61    len: usize,
62    buf: &mut B,
63    read_pair: F,
64) -> Result<VecMap<K, V>, DecodeError>
65where
66    F: Fn(&mut B) -> Result<(K, V), DecodeError>,
67{
68    let mut map = VecMap::with_capacity(len);
69    for _ in 0..len {
70        let (k, v) = read_pair(buf)?;
71        map.insert(k, v);
72    }
73    Ok(map)
74}
75
76/// Reads map length from the buffer
77///
78/// # Arguments
79///
80/// * `buf` - A reference to the Bytes containing the encoded map data.
81///
82/// # Returns
83///
84/// * `Ok(usize)` - Map length.
85/// * `Err(DecodeError)` - An error if the decoding process fails.
86///
87/// # Errors
88///
89/// This function will return an error if:
90/// - The buffer does not contain a map.
91/// - There is an error reading from the buffer.
92#[inline]
93pub fn read_map_len<T: DeserializableTraceData>(buf: &mut Buffer<T>) -> Result<usize, DecodeError> {
94    let buf = buf.as_mut_slice();
95    match decode::read_marker(buf)
96        .map_err(|_| DecodeError::InvalidFormat("Unable to read marker for map".to_owned()))?
97    {
98        Marker::FixMap(len) => Ok(len as usize),
99        Marker::Map16 => buf
100            .read_data_u16()
101            .map_err(|_| DecodeError::IOError)
102            .map(|len| len as usize),
103        Marker::Map32 => buf
104            .read_data_u32()
105            .map_err(|_| DecodeError::IOError)
106            .map(|len| len as usize),
107        _ => Err(DecodeError::InvalidType(
108            "Unable to read map from buffer".to_owned(),
109        )),
110    }
111}