libdd_trace_utils/msgpack_decoder/decode/
meta_struct.rs

1// Copyright 2024-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::map::{read_map, read_map_len};
6use crate::msgpack_decoder::decode::string::{handle_null_marker, read_string_ref};
7use libdd_tinybytes::Bytes;
8use rmp::decode;
9use std::collections::HashMap;
10
11fn read_byte_array_len(buf: &mut &[u8]) -> Result<u32, DecodeError> {
12    decode::read_bin_len(buf).map_err(|_| {
13        DecodeError::InvalidFormat("Unable to read binary len for meta_struct".to_owned())
14    })
15}
16
17#[inline]
18pub fn read_meta_struct<'a>(buf: &mut &'a [u8]) -> Result<HashMap<&'a str, Bytes>, DecodeError> {
19    if handle_null_marker(buf) {
20        return Ok(HashMap::default());
21    }
22
23    fn read_meta_struct_pair<'a>(buf: &mut &'a [u8]) -> Result<(&'a str, Bytes), DecodeError> {
24        let key = read_string_ref(buf)?;
25        let byte_array_len = read_byte_array_len(buf)? as usize;
26
27        let slice = buf.get(0..byte_array_len);
28        if let Some(slice) = slice {
29            let data = Bytes::copy_from_slice(slice);
30            *buf = &buf[byte_array_len..];
31            Ok((key, data))
32        } else {
33            Err(DecodeError::InvalidFormat(
34                "Invalid data length".to_string(),
35            ))
36        }
37    }
38
39    let len = read_map_len(buf)?;
40    read_map(len, buf, read_meta_struct_pair)
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn read_meta_test() {
49        let meta = HashMap::from([("key".to_string(), Bytes::from(vec![1, 2, 3, 4]))]);
50
51        let serialized = rmp_serde::to_vec_named(&meta).unwrap();
52        let mut slice = serialized.as_ref();
53        let res = read_meta_struct(&mut slice).unwrap();
54
55        assert_eq!(res.get("key").unwrap().to_vec(), vec![1, 2, 3, 4]);
56    }
57
58    #[test]
59    fn read_meta_wrong_family_test() {
60        let meta = HashMap::from([("key".to_string(), vec![1, 2, 3, 4])]);
61
62        let serialized = rmp_serde::to_vec_named(&meta).unwrap();
63        let mut slice = serialized.as_ref();
64        let res = read_meta_struct(&mut slice);
65
66        assert!(res.is_err());
67        matches!(res.unwrap_err(), DecodeError::InvalidFormat(_));
68    }
69}