LCOV - code coverage report
Current view: top level - datadog - msgpack.h (source / functions) Hit Total Coverage
Test: filtered.info Lines: 41 46 89.1 %
Date: 2024-01-03 20:30:12 Functions: 27 27 100.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : // This component provides encoding routines for [MessagePack][1].
       4             : //
       5             : // Each function is in `namespace msgpack` and appends a specified value to a
       6             : // `std::string`.  For example, `msgpack::pack_integer(destination, -42)`
       7             : // MessagePack encodes the number `-42` and appends the result to `destination`.
       8             : //
       9             : // Only encoding is provided, and only for the types required by `SpanData` and
      10             : // `DatadogAgent`.
      11             : //
      12             : // [1]: https://msgpack.org/index.html
      13             : 
      14             : #include <climits>
      15             : #include <cstddef>
      16             : #include <cstdint>
      17             : #include <string>
      18             : #include <utility>
      19             : 
      20             : #include "expected.h"
      21             : #include "string_view.h"
      22             : 
      23             : namespace datadog {
      24             : namespace tracing {
      25             : namespace msgpack {
      26             : 
      27             : void pack_integer(std::string& buffer, std::int64_t value);
      28             : void pack_integer(std::string& buffer, std::uint64_t value);
      29             : void pack_integer(std::string& buffer, std::int32_t value);
      30             : 
      31             : void pack_double(std::string& buffer, double value);
      32             : 
      33             : Expected<void> pack_string(std::string& buffer, StringView value);
      34             : Expected<void> pack_string(std::string& buffer, const char* begin,
      35             :                            std::size_t size);
      36             : 
      37             : Expected<void> pack_array(std::string& buffer, std::size_t size);
      38             : 
      39             : // Append to the specified `buffer` a MessagePack encoded array having the
      40             : // specified `values`, where for each element of `values` the specified
      41             : // `pack_value` function appends the value.  `pack_value` is invoked with two
      42             : // arguments: the first is a reference to `buffer`, and the second is a
      43             : // reference to the current value.  `pack_value` returns an `Expected<void>`. If
      44             : // the return value is an error, then iteration is halted and the error is
      45             : // returned.  If some other error occurs, then an error is returned.  Otherwise,
      46             : // the non-error value is returned.
      47             : template <typename Iterable, typename PackValue>
      48             : Expected<void> pack_array(std::string& buffer, Iterable&& values,
      49             :                           PackValue&& pack_value);
      50             : 
      51             : Expected<void> pack_map(std::string& buffer, std::size_t size);
      52             : 
      53             : // Append to the specified `buffer` a MessagePack encoded map consisting of the
      54             : // specified `pairs`, where the first element of each pair is the name of the
      55             : // map element, and the second element of each pair is some value that is
      56             : // MessagePack encoded by the specified `pack_value` function. `pack_value` is
      57             : // invoked with two arguments: the first is a reference to `buffer`, and the
      58             : // second is a reference to the current value.  `pack_value` returns an
      59             : // `Expected<void>`. If the return value is an error, then iteration is halted
      60             : // and the error is returned.  If some other error occurs, then an error is
      61             : // returned.  Otherwise, the non-error value is returned.
      62             : template <typename PairIterable, typename PackValue>
      63             : Expected<void> pack_map(std::string& buffer, const PairIterable& pairs,
      64             :                         PackValue&& pack_value);
      65             : 
      66             : // Append to the specified `buffer` a MessagePack encoded map consisting of the
      67             : // specified key value pairs.  After the `buffer` argument, `pack_map` accepts
      68             : // an even number of arguments.  First in each pair of arguments is `key`, the
      69             : // key name of the corresponding map item.  Second in each pair of arguments is
      70             : // `pack_value`, a function that encodes the corresponding value.  `pack_value`
      71             : // is invoked with one argument: a reference to `buffer`. `pack_value` returns
      72             : // an `Expected<void>`.  If the return value is an error, then iteration is
      73             : // halted and the error is returned.  If some other error occurs, then an error
      74             : // is returned.  Otherwise, the non-error value is returned.
      75             : template <typename PackValue, typename... Rest>
      76             : Expected<void> pack_map(std::string& buffer, StringView key,
      77             :                         PackValue&& pack_value, Rest&&... rest);
      78             : 
      79             : template <typename PackValue, typename... Rest>
      80             : Expected<void> pack_map_suffix(std::string& buffer, StringView key,
      81             :                                PackValue&& pack_value, Rest&&... rest);
      82             : Expected<void> pack_map_suffix(std::string& buffer);
      83             : 
      84             : template <typename Iterable, typename PackValue>
      85         838 : Expected<void> pack_array(std::string& buffer, Iterable&& values,
      86             :                           PackValue&& pack_value) {
      87         838 :   Expected<void> result;
      88         838 :   result = pack_array(buffer, std::size(values));
      89         838 :   if (!result) {
      90           1 :     return result;
      91             :   }
      92        1674 :   for (const auto& value : values) {
      93         838 :     result = pack_value(buffer, value);
      94         838 :     if (!result) {
      95           1 :       break;
      96             :     }
      97             :   }
      98         837 :   return result;
      99           0 : }
     100             : 
     101             : template <typename PairIterable, typename PackValue>
     102         840 : Expected<void> pack_map(std::string& buffer, const PairIterable& pairs,
     103             :                         PackValue&& pack_value) {
     104         840 :   Expected<void> result;
     105         840 :   result = pack_map(buffer, std::size(pairs));
     106         840 :   if (!result) {
     107           1 :     return result;
     108             :   }
     109        3757 :   for (const auto& [key, value] : pairs) {
     110        2919 :     result = pack_string(buffer, key);
     111        2919 :     if (!result) {
     112           0 :       break;
     113             :     }
     114        2919 :     result = pack_value(buffer, value);
     115        2919 :     if (!result) {
     116           1 :       break;
     117             :     }
     118             :   }
     119         839 :   return result;
     120           0 : }
     121             : 
     122             : template <typename PackValue, typename... Rest>
     123         420 : Expected<void> pack_map(std::string& buffer, StringView key,
     124             :                         PackValue&& pack_value, Rest&&... rest) {
     125             :   static_assert(
     126             :       sizeof...(rest) % 2 == 0,
     127             :       "pack_map must receive an even number of arguments after the first.");
     128             :   static_assert(
     129             :       sizeof...(rest) / 2 <= UINT32_MAX,
     130             :       "You're passing more than eight billion arguments to a function.");
     131         420 :   (void)pack_map(buffer, 1 + sizeof...(rest) / 2);
     132             : 
     133             :   return pack_map_suffix(buffer, key, std::forward<PackValue>(pack_value),
     134         420 :                          std::forward<Rest>(rest)...);
     135             : }
     136             : 
     137             : template <typename PackValue, typename... Rest>
     138        5030 : Expected<void> pack_map_suffix(std::string& buffer, StringView key,
     139             :                                PackValue&& pack_value, Rest&&... rest) {
     140        5030 :   Expected<void> result;
     141        5030 :   result = pack_string(buffer, key);
     142        5030 :   if (!result) {
     143           0 :     return result;
     144             :   }
     145        5030 :   result = pack_value(buffer);
     146        5030 :   if (!result) {
     147           1 :     return result;
     148             :   }
     149        5029 :   result = pack_map_suffix(buffer, std::forward<Rest>(rest)...);
     150        5029 :   return result;
     151           0 : }
     152             : 
     153         419 : inline Expected<void> pack_map_suffix(std::string&) {
     154             :   // base case does nothing
     155         419 :   return {};
     156             : }
     157             : 
     158         419 : inline void pack_integer(std::string& buffer, std::int32_t value) {
     159         419 :   pack_integer(buffer, std::int64_t(value));
     160         419 : }
     161             : 
     162       11294 : inline Expected<void> pack_string(std::string& buffer, StringView value) {
     163       11294 :   return pack_string(buffer, value.begin(), value.size());
     164             : }
     165             : 
     166             : }  // namespace msgpack
     167             : }  // namespace tracing
     168             : }  // namespace datadog

Generated by: LCOV version 1.16