LCOV - code coverage report
Current view: top level - libbpfilter/include/bpfilter - pack.h (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 100.0 % 26 26
Test Date: 2025-11-24 12:34:34 Functions: - 0 0
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :             : /*
       3                 :             :  * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #pragma once
       7                 :             : 
       8                 :             : #include <stdbool.h>
       9                 :             : #include <stddef.h>
      10                 :             : #include <stdint.h>
      11                 :             : 
      12                 :             : #include <bpfilter/logger.h>
      13                 :             : 
      14                 :             : /**
      15                 :             :  * @file pack.h
      16                 :             :  *
      17                 :             :  * Serialization is used to send/receive bpfilter objects to and from the
      18                 :             :  * daemon. While bpfilter originally used a custom logic to convert its objects
      19                 :             :  * into binary data, it was inefficient and didn't support different versions of
      20                 :             :  * the same object (when fields are added or removed). Instead, the new packing
      21                 :             :  * logic provides an API to (de)serialize bpfilter objects using
      22                 :             :  * [MessagePack](https://msgpack.org).
      23                 :             :  *
      24                 :             :  * The packing mechanism doesn't implement the MessagePack protocol directly,
      25                 :             :  * but relies on the [MPack](https://ludocode.github.io/mpack/) implementation
      26                 :             :  * instead. MPack provides the following advantages:
      27                 :             :  * - Fast (de)serialization: 4x faster than the previous custom serialization
      28                 :             :  *   logic, and 10x faster than Jansson.
      29                 :             :  * - Named fields: each serialized field of an object is named, allowing the
      30                 :             :  *   objects to evolve and introduce or remove new fields while maintaining
      31                 :             :  *   backward compatibility.
      32                 :             :  * - Can be used in place: existing objects format can be used as-is, without
      33                 :             :  *   extra field dedicated to the serializer or schema file (hello Protobuf
      34                 :             :  *   and Thrift).
      35                 :             :  *
      36                 :             :  * Two different packing objects are provided:
      37                 :             :  * - `bf_wpack_t`: the writer object, to serialize data. To keep the
      38                 :             :  *   the serialization as simple as possible, no error will be returned when
      39                 :             :  *   a field is serialized. Instead, users must use `bf_wpack_is_valid` to
      40                 :             :  *   validate the serialized data before it is exported. This behaviour is
      41                 :             :  *   different for the rest of the core module, but is justified for usability
      42                 :             :  *   reasons.
      43                 :             :  * - `bf_rpack_t`: node-based API to read serialized data. Each serialized field
      44                 :             :  *   can be represented as a node. The object deserialization functions should
      45                 :             :  *   expect to receive a node which represents them.
      46                 :             :  *
      47                 :             :  * ## Serializing
      48                 :             :  * `bf_wpack_t` always have a root node containing key-value pairs. Keys should
      49                 :             :  * be strings, and values can be any primal type, array, or another object.
      50                 :             :  * `bf_wpack_kv_TYPE` functions should be used to write both the key and the
      51                 :             :  * value in an object, `bf_wpack_TYPE` functions should be used to write single
      52                 :             :  * objects (without a key) into arrays.
      53                 :             :  * To nest objects and arrays, use `bf_wpack_open_object` and
      54                 :             :  * `bf_wpack_open_array`, they both allow the caller to provide a key: if the
      55                 :             :  * object (or array) is inserted into an object you should provide a key, if the
      56                 :             :  * object (or array) is inserted into an array you should not provide a key. In
      57                 :             :  * any case, call `bf_wpack_close_object` or `bf_wpack_close_array` to complete
      58                 :             :  * the nested object/array.
      59                 :             :  * Before using the serialized data, ensure it is valid with `bf_wpack_is_valid`,
      60                 :             :  * as not error will be returned during the pack creation.
      61                 :             :  *
      62                 :             :  * ## Deserializing
      63                 :             :  * `bf_rpack_t` is the deserialization object, although we do not read directly
      64                 :             :  * from it. Instead, one should get the root object with `bf_rpack_root`, then
      65                 :             :  * query keys from it.
      66                 :             :  * All the functions used to deserialize data from the pack are available in two
      67                 :             :  * formats:
      68                 :             :  * - `bf_rpack_TYPE`: read a typed value from a node.
      69                 :             :  * - `bf_rpack_kv_TYPE`: read the value identified by a key in an object node.
      70                 :             :  * To prevent any tempering or corruption, every function able to read data from
      71                 :             :  * a node will return a value: 0 on success, or a negative integer on failure.
      72                 :             :  *
      73                 :             :  * @note To ensure compatibility of the binary data over time, the following
      74                 :             :  * constraints must be followed:
      75                 :             :  * - Every enumeration value is serialized as integer: it should support every
      76                 :             :  *   possible enumeration value used by bpfilter, including negative values.
      77                 :             :  * - `size_t` values are serialied as `uint64_t`: for similar reasons to he
      78                 :             :  *   enumerations.
      79                 :             :  *
      80                 :             :  * @todo `bf_wpack_kv_TYPE` functions should only write into objects.
      81                 :             :  * @todo `bf_wpack_TYPE` functions should only write into arrays.
      82                 :             :  * @todo Create dedicated functions to pack and unpack a `size_t` and `ssize_t`.
      83                 :             :  * @todo Functions that write to the pack object should be more verbose: even
      84                 :             :  * if they don't return an error code, they should log a warning when a packing
      85                 :             :  * operation fails.
      86                 :             :  */
      87                 :             : 
      88                 :             : struct bf_wpack;
      89                 :             : typedef struct bf_wpack bf_wpack_t;
      90                 :             : 
      91                 :             : struct bf_list;
      92                 :             : typedef struct bf_list bf_list;
      93                 :             : 
      94                 :             : /// @brief Cleanup attribute for dynamically allocated `bf_wpack_t` objects.
      95                 :             : #define _free_bf_wpack_ __attribute__((cleanup(bf_wpack_free)))
      96                 :             : 
      97                 :             : /**
      98                 :             :  * @brief Allocate and initialize a new `bf_wpack_t` object.
      99                 :             :  *
     100                 :             :  * @param pack `bf_wpack_t` object to allocate and initialize. Can't be NULL.
     101                 :             :  * @return 0 on sucess, or a negative error value on failure.
     102                 :             :  */
     103                 :             : int bf_wpack_new(bf_wpack_t **pack);
     104                 :             : 
     105                 :             : /**
     106                 :             :  * @brief Deinitialize and deallocate a `bf_wpack_t` object.
     107                 :             :  *
     108                 :             :  * @param pack `bf_wpack_t` object to deallocate and deinitialize. Can't be
     109                 :             :  *        NULL. If `*pack` is NULL, this function has no effect.
     110                 :             :  */
     111                 :             : void bf_wpack_free(bf_wpack_t **pack);
     112                 :             : 
     113                 :             : /**
     114                 :             :  * @brief Check if the serialized data is valid.
     115                 :             :  *
     116                 :             :  * @param pack `bf_wpack_t` object to check. Can't be NULL.
     117                 :             :  * @return True if the serialized data is valid, false otherwise.
     118                 :             :  */
     119                 :             : bool bf_wpack_is_valid(bf_wpack_t *pack);
     120                 :             : 
     121                 :             : /**
     122                 :             :  * @brief Get the serialized data.
     123                 :             :  *
     124                 :             :  * Ensure the buffer is flushed and all the remaining data has been serialized.
     125                 :             :  * On success, `*data` points to a buffer containing `data_len` bytes. The
     126                 :             :  * caller do not own the data.
     127                 :             :  *
     128                 :             :  * @return 0 on success, or a negative error value on failure.
     129                 :             :  */
     130                 :             : int bf_wpack_get_data(bf_wpack_t *pack, const void **data, size_t *data_len);
     131                 :             : 
     132                 :             : void bf_wpack_nil(bf_wpack_t *pack);
     133                 :             : void bf_wpack_int(bf_wpack_t *pack, int value);
     134                 :             : void bf_wpack_uint(bf_wpack_t *pack, unsigned int value);
     135                 :             : void bf_wpack_u8(bf_wpack_t *pack, uint8_t value);
     136                 :             : void bf_wpack_u16(bf_wpack_t *pack, uint16_t value);
     137                 :             : void bf_wpack_u32(bf_wpack_t *pack, uint32_t value);
     138                 :             : void bf_wpack_u64(bf_wpack_t *pack, uint64_t value);
     139                 :             : void bf_wpack_bool(bf_wpack_t *pack, bool value);
     140                 :             : void bf_wpack_str(bf_wpack_t *pack, const char *value);
     141                 :             : void bf_wpack_bin(bf_wpack_t *pack, const void *value, size_t len);
     142                 :             : void bf_wpack_list(bf_wpack_t *pack, const bf_list *value);
     143                 :             : #define bf_wpack_enum(pack, value) bf_wpack_int((pack), (value))
     144                 :             : 
     145                 :             : static inline void bf_wpack_kv_nil(bf_wpack_t *pack, const char *key)
     146                 :             : {
     147                 :         836 :     bf_wpack_str(pack, key);
     148                 :         836 :     bf_wpack_nil(pack);
     149                 :         834 : }
     150                 :             : 
     151                 :             : static inline void bf_wpack_kv_int(bf_wpack_t *pack, const char *key, int value)
     152                 :             : {
     153                 :       20614 :     bf_wpack_str(pack, key);
     154                 :       20614 :     bf_wpack_int(pack, value);
     155                 :          53 : }
     156                 :             : 
     157                 :             : static inline void bf_wpack_kv_uint(bf_wpack_t *pack, const char *key,
     158                 :             :                                     unsigned int value)
     159                 :             : {
     160                 :          25 :     bf_wpack_str(pack, key);
     161                 :          25 :     bf_wpack_uint(pack, value);
     162                 :          23 : }
     163                 :             : 
     164                 :             : static inline void bf_wpack_kv_u8(bf_wpack_t *pack, const char *key,
     165                 :             :                                   uint8_t value)
     166                 :             : {
     167                 :        1887 :     bf_wpack_str(pack, key);
     168                 :        1887 :     bf_wpack_u8(pack, value);
     169                 :             : }
     170                 :             : 
     171                 :             : static inline void bf_wpack_kv_u16(bf_wpack_t *pack, const char *key,
     172                 :             :                                    uint16_t value)
     173                 :             : {
     174                 :           2 :     bf_wpack_str(pack, key);
     175                 :           2 :     bf_wpack_u16(pack, value);
     176                 :             : }
     177                 :             : 
     178                 :             : static inline void bf_wpack_kv_u32(bf_wpack_t *pack, const char *key,
     179                 :             :                                    uint32_t value)
     180                 :             : {
     181                 :        1888 :     bf_wpack_str(pack, key);
     182                 :        1888 :     bf_wpack_u32(pack, value);
     183                 :             : }
     184                 :             : 
     185                 :             : static inline void bf_wpack_kv_u64(bf_wpack_t *pack, const char *key,
     186                 :             :                                    uint64_t value)
     187                 :             : {
     188                 :        5231 :     bf_wpack_str(pack, key);
     189                 :        5231 :     bf_wpack_u64(pack, value);
     190                 :             : }
     191                 :             : 
     192                 :             : static inline void bf_wpack_kv_bool(bf_wpack_t *pack, const char *key,
     193                 :             :                                     bool value)
     194                 :             : {
     195                 :        1888 :     bf_wpack_str(pack, key);
     196                 :        1888 :     bf_wpack_bool(pack, value);
     197                 :             : }
     198                 :             : 
     199                 :             : static inline void bf_wpack_kv_str(bf_wpack_t *pack, const char *key,
     200                 :             :                                    const char *str)
     201                 :             : {
     202                 :        1703 :     bf_wpack_str(pack, key);
     203                 :        1703 :     bf_wpack_str(pack, str);
     204                 :          74 : }
     205                 :             : 
     206                 :             : static inline void bf_wpack_kv_bin(bf_wpack_t *pack, const char *key,
     207                 :             :                                    const void *data, size_t data_len)
     208                 :             : {
     209                 :        9500 :     bf_wpack_str(pack, key);
     210                 :        9500 :     bf_wpack_bin(pack, data, data_len);
     211                 :             : }
     212                 :             : 
     213                 :             : static inline void bf_wpack_kv_enum(bf_wpack_t *pack, const char *key,
     214                 :             :                                     int value)
     215                 :             : {
     216                 :        2517 :     bf_wpack_str(pack, key);
     217                 :        2517 :     bf_wpack_enum(pack, value);
     218                 :             : }
     219                 :             : 
     220                 :             : void bf_wpack_kv_list(bf_wpack_t *pack, const char *key, const bf_list *value);
     221                 :             : 
     222                 :             : /**
     223                 :             :  * @brief Open a new object in the pack.
     224                 :             :  *
     225                 :             :  * Once this function returns, any call to `bf_wpack_TYPE` or `bf_wpack_kv_TYPE`
     226                 :             :  * will insert data into the object.
     227                 :             :  *
     228                 :             :  * @param pack `bf_wpack_t` object to open the object in. Can't be NULL.
     229                 :             :  * @param key Key to use for the object. If NULL, no key is inserted.
     230                 :             :  */
     231                 :             : void bf_wpack_open_object(bf_wpack_t *pack, const char *key);
     232                 :             : 
     233                 :             : /**
     234                 :             :  * @brief Close the current object.
     235                 :             :  *
     236                 :             :  * Once the object is closed, any call to `bf_wpack_TYPE` or `bf_wpack_kv_TYPE`
     237                 :             :  * will insert data into the parent object or array.
     238                 :             :  *
     239                 :             :  * @param pack `bf_wpack_t` object to close the object in. Can't be NULL.
     240                 :             :  */
     241                 :             : void bf_wpack_close_object(bf_wpack_t *pack);
     242                 :             : 
     243                 :             : /**
     244                 :             :  * @brief Open a new array in the pack.
     245                 :             :  *
     246                 :             :  * Once this function returns, any call to `bf_wpack_TYPE` or `bf_wpack_kv_TYPE`
     247                 :             :  * will insert data into the array.
     248                 :             :  *
     249                 :             :  * @param pack `bf_wpack_t` object to open the array in. Can't be NULL.
     250                 :             :  * @param key Key to use for the array. If NULL, no key is inserted.
     251                 :             :  */
     252                 :             : void bf_wpack_open_array(bf_wpack_t *pack, const char *key);
     253                 :             : 
     254                 :             : /**
     255                 :             :  * @brief Close the current array.
     256                 :             :  *
     257                 :             :  * Once the array is closed, any call to `bf_wpack_TYPE` or `bf_wpack_kv_TYPE`
     258                 :             :  * will insert data into the parent object or array.
     259                 :             :  *
     260                 :             :  * @param pack `bf_wpack_t` object to close the array in. Can't be NULL.
     261                 :             :  */
     262                 :             : void bf_wpack_close_array(bf_wpack_t *pack);
     263                 :             : 
     264                 :             : struct bf_rpack;
     265                 :             : typedef struct bf_rpack bf_rpack_t;
     266                 :             : 
     267                 :             : /**
     268                 :             :  * @brief Opaque structure to pass nodes by value.
     269                 :             :  */
     270                 :             : typedef union
     271                 :             : {
     272                 :             :     char _opaque[16];
     273                 :             :     void *_align;
     274                 :             : } bf_rpack_node_t;
     275                 :             : 
     276                 :             : /// @brief Cleanup attribute for dynamically allocated `bf_rpack_t` objects.
     277                 :             : #define _free_bf_rpack_ __attribute__((cleanup(bf_rpack_free)))
     278                 :             : 
     279                 :             : /**
     280                 :             :  * @brief Loop over all the nodes in an array node.
     281                 :             :  *
     282                 :             :  * The counter `i` is accessible within the scope.
     283                 :             :  *
     284                 :             :  * @warning This loop must ensure we don't query the node for invalid data:
     285                 :             :  * we should not request a node from the array if it's empty, of if the index
     286                 :             :  * is out of the array. Otherwise, it would put the `bf_rpack_t` object in
     287                 :             :  * failure mode.
     288                 :             :  *
     289                 :             :  * @param node Array node. If the node is not an array, the loop will be
     290                 :             :  *        ignored.
     291                 :             :  * @param value_node A node in the array, updated on each iteration.
     292                 :             :  */
     293                 :             : #define bf_rpack_array_foreach(node, value_node)                               \
     294                 :             :     for (size_t i = ((bf_rpack_array_count(node) ?                             \
     295                 :             :                           ((value_node) = bf_rpack_array_value_at(node, 0)) :  \
     296                 :             :                           (bf_rpack_node_t) {}),                               \
     297                 :             :                      0);                                                       \
     298                 :             :          i < bf_rpack_array_count(node);                                       \
     299                 :             :          ++i, (value_node) = (i < bf_rpack_array_count(node) ?                 \
     300                 :             :                                   bf_rpack_array_value_at(node, i) :           \
     301                 :             :                                   (bf_rpack_node_t) {}))
     302                 :             : 
     303                 :             : /**
     304                 :             :  * @brief Read an named enumerator value from a node.
     305                 :             :  *
     306                 :             :  * This macro will ensure the enumerator value is properly casted from the
     307                 :             :  * corresponding integer stored in the pack.
     308                 :             :  *
     309                 :             :  * @param node Node to read from.
     310                 :             :  * @param key Key of the node to read. Can't be NULL.
     311                 :             :  * @param value Pointer to the enumerator value to read into.
     312                 :             :  * @return 0 on success, or a negative error value on failure.
     313                 :             :  */
     314                 :             : #define bf_rpack_kv_enum(node, key, value)                                     \
     315                 :             :     ({                                                                         \
     316                 :             :         int __value;                                                           \
     317                 :             :         int __r = bf_rpack_kv_int(node, key, &__value);                        \
     318                 :             :         if (!__r)                                                              \
     319                 :             :             *(value) = __value;                                                \
     320                 :             :         __r;                                                                   \
     321                 :             :     })
     322                 :             : 
     323                 :             : /**
     324                 :             :  * @brief Read an enumerator value from a node.
     325                 :             :  *
     326                 :             :  * Similar to `bf_rpack_kv_enum` but reads a node directly.
     327                 :             :  *
     328                 :             :  * @param node Node to read from.
     329                 :             :  * @param value Pointer to the enumerator value to read into.
     330                 :             :  * @return 0 on success, or a negative error value on failure.
     331                 :             :  */
     332                 :             : #define bf_rpack_enum(node, value)                                             \
     333                 :             :     ({                                                                         \
     334                 :             :         int __value;                                                           \
     335                 :             :         int __r = bf_rpack_int(node, &__value);                                \
     336                 :             :         if (!__r)                                                              \
     337                 :             :             *(value) = __value;                                                \
     338                 :             :         __r;                                                                   \
     339                 :             :     })
     340                 :             : 
     341                 :             : /**
     342                 :             :  * @brief Log a missing key error and return a negative error value.
     343                 :             :  *
     344                 :             :  * @param v The error value to return.
     345                 :             :  * @param key The missing key, as a string.
     346                 :             :  */
     347                 :             : #define bf_rpack_key_err(v, key) bf_err_r(v, "failed to read %s from pack", key)
     348                 :             : 
     349                 :             : /**
     350                 :             :  * @brief Allocate and initialize a new `bf_rpack_t` object.
     351                 :             :  *
     352                 :             :  * @param pack `bf_rpack_t` object to allocate and initialize. Can't be NULL.
     353                 :             :  * @param data Serialized data. To prevent large copies, the deserialization
     354                 :             :  *        object won't take ownership of the data. Can't be NULL.
     355                 :             :  * @param data_len Length of `data`.
     356                 :             :  * @return 0 on success, or a negative error value on failure.
     357                 :             :  */
     358                 :             : int bf_rpack_new(bf_rpack_t **pack, const void *data, size_t data_len);
     359                 :             : 
     360                 :             : /**
     361                 :             :  * @brief Deinitialize and deallocate a `bf_rpack_t` object.
     362                 :             :  *
     363                 :             :  * @param pack `bf_rpack_t` object to deallocate and deinitialize. Can't be
     364                 :             :  *        NULL. If `*pack` is NULL, this function has no effect.
     365                 :             :  */
     366                 :             : void bf_rpack_free(bf_rpack_t **pack);
     367                 :             : 
     368                 :             : /**
     369                 :             :  * @brief Get the root node of `pack`.
     370                 :             :  *
     371                 :             :  * @param pack `bf_rpack_t` object to get the root node from. Can't be NULL.
     372                 :             :  * @return Root node for `pack`.
     373                 :             :  */
     374                 :             : bf_rpack_node_t bf_rpack_root(const bf_rpack_t *pack);
     375                 :             : 
     376                 :             : /**
     377                 :             :  * @brief Returns true if the node is nil, false otherwise.
     378                 :             :  *
     379                 :             :  * Nil nodes are used to specific an absent value (e.g. optional `bf_hookopts`).
     380                 :             :  *
     381                 :             :  * @param node Node to check for nil.
     382                 :             :  * @return True if `node` is nil, false otherwise.
     383                 :             :  */
     384                 :             : bool bf_rpack_is_nil(bf_rpack_node_t node);
     385                 :             : 
     386                 :             : /**
     387                 :             :  * @brief Returns true if the node is an array, false otherwise.
     388                 :             :  *
     389                 :             :  * @param node Node to check for array type.
     390                 :             :  * @return True if `node` is an array, false otherwise.
     391                 :             :  */
     392                 :             : bool bf_rpack_is_array(bf_rpack_node_t node);
     393                 :             : 
     394                 :             : /**
     395                 :             :  * @brief Returns the number of elements in an array node.
     396                 :             :  *
     397                 :             :  * To ensure the returned value is relevant, the caller should ensure `node` is
     398                 :             :  * an array.
     399                 :             :  *
     400                 :             :  * @param node Array node to get the number of elements of.
     401                 :             :  * @return The number of elements in `node`, or 0 if `node` is not an array.
     402                 :             :  */
     403                 :             : size_t bf_rpack_array_count(bf_rpack_node_t node);
     404                 :             : 
     405                 :             : /**
     406                 :             :  * @brief Get an array element by index.
     407                 :             :  *
     408                 :             :  * The caller is responsible for ensuring `node` is an array and `index` is a
     409                 :             :  * valid index in `node`, otherwise the returned node will be invalid.
     410                 :             :  *
     411                 :             :  * @param node Array node to get elements from.
     412                 :             :  * @param index Index of the node to get.
     413                 :             :  * @return The node of the element as `index` in `node`. */
     414                 :             : bf_rpack_node_t bf_rpack_array_value_at(bf_rpack_node_t node, size_t index);
     415                 :             : 
     416                 :             : /**
     417                 :             :  * @brief Check if an object node contains a given key.
     418                 :             :  *
     419                 :             :  * The caller is responsible for ensuring `node` is a valid object node. If
     420                 :             :  * `node` is invalid or the wrong type, false is returned.
     421                 :             :  *
     422                 :             :  * @param node Object node to check.
     423                 :             :  * @param key Key to check in `node`. Can't be NULL.
     424                 :             :  * @return True if `key` is a valid key in `node`, false otherwise. On error,
     425                 :             :  *         false is returned.
     426                 :             :  */
     427                 :             : bool bf_rpack_kv_contains(bf_rpack_node_t node, const char *key);
     428                 :             : 
     429                 :             : int bf_rpack_int(bf_rpack_node_t node, int *value);
     430                 :             : int bf_rpack_uint(bf_rpack_node_t node, unsigned int *value);
     431                 :             : int bf_rpack_u8(bf_rpack_node_t node, uint8_t *value);
     432                 :             : int bf_rpack_u16(bf_rpack_node_t node, uint16_t *value);
     433                 :             : int bf_rpack_u32(bf_rpack_node_t node, uint32_t *value);
     434                 :             : int bf_rpack_u64(bf_rpack_node_t node, uint64_t *value);
     435                 :             : int bf_rpack_str(bf_rpack_node_t node, char **value);
     436                 :             : int bf_rpack_bool(bf_rpack_node_t node, bool *value);
     437                 :             : int bf_rpack_bin(bf_rpack_node_t node, const void **data, size_t *data_len);
     438                 :             : 
     439                 :             : int bf_rpack_kv_node(bf_rpack_node_t node, const char *key,
     440                 :             :                      bf_rpack_node_t *child);
     441                 :             : int bf_rpack_kv_int(bf_rpack_node_t node, const char *key, int *value);
     442                 :             : int bf_rpack_kv_uint(bf_rpack_node_t node, const char *key,
     443                 :             :                      unsigned int *value);
     444                 :             : int bf_rpack_kv_u8(bf_rpack_node_t node, const char *key, uint8_t *value);
     445                 :             : int bf_rpack_kv_u16(bf_rpack_node_t node, const char *key, uint16_t *value);
     446                 :             : int bf_rpack_kv_u32(bf_rpack_node_t node, const char *key, uint32_t *value);
     447                 :             : int bf_rpack_kv_u64(bf_rpack_node_t node, const char *key, uint64_t *value);
     448                 :             : int bf_rpack_kv_str(bf_rpack_node_t node, const char *key, char **value);
     449                 :             : int bf_rpack_kv_bool(bf_rpack_node_t node, const char *key, bool *value);
     450                 :             : int bf_rpack_kv_bin(bf_rpack_node_t node, const char *key, const void **data,
     451                 :             :                     size_t *data_len);
     452                 :             : int bf_rpack_kv_obj(bf_rpack_node_t node, const char *key,
     453                 :             :                     bf_rpack_node_t *child);
     454                 :             : int bf_rpack_kv_array(bf_rpack_node_t node, const char *key,
     455                 :             :                       bf_rpack_node_t *child);
        

Generated by: LCOV version 2.0-1