LCOV - code coverage report
Current view: top level - libbpfilter - pack.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 86.1 % 280 241
Test Date: 2025-09-16 14:46:44 Functions: 84.0 % 50 42

            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              : #include "bpfilter/pack.h"
       7              : 
       8              : #include "bpfilter/helper.h"
       9              : #include "bpfilter/list.h"
      10              : #include "bpfilter/logger.h"
      11              : #include "mpack.h"
      12              : 
      13              : struct bf_wpack
      14              : {
      15              :     void *data;
      16              :     size_t data_len;
      17              :     size_t data_cap;
      18              : 
      19              :     char buffer[64];
      20              :     mpack_writer_t writer;
      21              : };
      22              : 
      23           40 : static void _bf_wpack_writer_flush_cb(mpack_writer_t *writer,
      24              :                                       const char *buffer, size_t count)
      25              : {
      26           40 :     bf_wpack_t *pack = writer->context;
      27              :     int r;
      28              : 
      29           40 :     if (pack->data_cap <= pack->data_len + count) {
      30           23 :         size_t new_cap = pack->data_cap ?: 64;
      31              : 
      32           38 :         while (new_cap <= pack->data_len + count)
      33           15 :             new_cap <<= 1;
      34              : 
      35           23 :         r = bf_realloc(&pack->data, new_cap);
      36           23 :         if (r)
      37            0 :             mpack_writer_flag_error(writer, mpack_error_memory);
      38              : 
      39           23 :         pack->data_cap = new_cap;
      40              :     }
      41              : 
      42           40 :     memcpy(pack->data + pack->data_len, buffer, count);
      43           40 :     pack->data_len += count;
      44           40 : }
      45              : 
      46            8 : int bf_wpack_new(bf_wpack_t **pack)
      47              : {
      48              :     bf_wpack_t *_pack = NULL;
      49              : 
      50            8 :     bf_assert(pack);
      51              : 
      52            8 :     _pack = malloc(sizeof(*_pack));
      53            8 :     if (!_pack)
      54              :         return -ENOMEM;
      55              : 
      56            8 :     _pack->data = NULL;
      57            8 :     _pack->data_cap = 0;
      58            8 :     _pack->data_len = 0;
      59              : 
      60            8 :     mpack_writer_init(&_pack->writer, _pack->buffer, 64);
      61              : 
      62              :     /* Use a custom flush function so we can control the flush
      63              :      * (e.g. when get_data() is called). */
      64            8 :     mpack_writer_set_flush(&_pack->writer, _bf_wpack_writer_flush_cb);
      65              :     mpack_writer_set_context(&_pack->writer, _pack);
      66              : 
      67            8 :     mpack_build_map(&_pack->writer);
      68              : 
      69            8 :     *pack = TAKE_PTR(_pack);
      70              : 
      71            8 :     return 0;
      72              : }
      73              : 
      74            8 : void bf_wpack_free(bf_wpack_t **pack)
      75              : {
      76              :     bf_wpack_t *_pack;
      77              : 
      78            8 :     bf_assert(pack);
      79              : 
      80            8 :     _pack = *pack;
      81            8 :     if (!_pack)
      82              :         return;
      83              : 
      84            8 :     mpack_writer_destroy(&_pack->writer);
      85              : 
      86              :     freep((void *)&_pack->data);
      87              :     freep((void *)pack);
      88              : }
      89              : 
      90           71 : bool bf_wpack_is_valid(bf_wpack_t *pack)
      91              : {
      92              :     mpack_error_t error;
      93              : 
      94           71 :     bf_assert(pack);
      95              : 
      96              :     error = mpack_writer_error(&pack->writer);
      97           71 :     if (error != mpack_ok)
      98            0 :         return false;
      99              : 
     100              :     return true;
     101              : }
     102              : 
     103            8 : int bf_wpack_get_data(bf_wpack_t *pack, const void **data, size_t *data_len)
     104              : {
     105            8 :     bf_assert(pack);
     106            8 :     bf_assert(data);
     107            8 :     bf_assert(data_len);
     108              : 
     109            8 :     mpack_complete_map(&pack->writer);
     110              : 
     111            8 :     mpack_writer_flush_message(&pack->writer);
     112            8 :     if (!bf_wpack_is_valid(pack))
     113              :         return -EINVAL;
     114              : 
     115            8 :     *data_len = pack->data_len;
     116            8 :     *data = pack->data;
     117              : 
     118            8 :     return 0;
     119              : }
     120              : 
     121            2 : void bf_wpack_nil(bf_wpack_t *pack)
     122              : {
     123            2 :     mpack_write_nil(&pack->writer);
     124            2 : }
     125              : 
     126           61 : void bf_wpack_int(bf_wpack_t *pack, int value)
     127              : {
     128           61 :     mpack_write_int(&pack->writer, value);
     129           61 : }
     130              : 
     131            0 : void bf_wpack_uint(bf_wpack_t *pack, unsigned int value)
     132              : {
     133            0 :     mpack_write_uint(&pack->writer, value);
     134            0 : }
     135              : 
     136            5 : void bf_wpack_u8(bf_wpack_t *pack, uint8_t value)
     137              : {
     138            5 :     mpack_write_u8(&pack->writer, value);
     139            5 : }
     140              : 
     141            0 : void bf_wpack_u16(bf_wpack_t *pack, uint16_t value)
     142              : {
     143            0 :     mpack_write_u16(&pack->writer, value);
     144            0 : }
     145              : 
     146            5 : void bf_wpack_u32(bf_wpack_t *pack, uint32_t value)
     147              : {
     148            5 :     mpack_write_u32(&pack->writer, value);
     149            5 : }
     150              : 
     151           39 : void bf_wpack_u64(bf_wpack_t *pack, uint64_t value)
     152              : {
     153           39 :     mpack_write_u64(&pack->writer, value);
     154           39 : }
     155              : 
     156            5 : void bf_wpack_bool(bf_wpack_t *pack, bool value)
     157              : {
     158            5 :     mpack_write_bool(&pack->writer, value);
     159            5 : }
     160              : 
     161          179 : void bf_wpack_str(bf_wpack_t *pack, const char *value)
     162              : {
     163          179 :     mpack_write_cstr(&pack->writer, value);
     164          179 : }
     165              : 
     166           36 : void bf_wpack_bin(bf_wpack_t *pack, const void *value, size_t len)
     167              : {
     168           36 :     bf_assert(pack);
     169           36 :     bf_assert(value);
     170              : 
     171           36 :     mpack_write_bin(&pack->writer, value, len);
     172           36 : }
     173              : 
     174           10 : void bf_wpack_list(bf_wpack_t *pack, const bf_list *value)
     175              : {
     176              :     int r;
     177              : 
     178           10 :     bf_assert(pack);
     179           10 :     bf_assert(value);
     180              : 
     181           10 :     bf_wpack_open_array(pack, NULL);
     182           10 :     r = bf_list_pack(value, pack);
     183           10 :     if (r)
     184            0 :         mpack_writer_flag_error(&pack->writer, mpack_error_invalid);
     185           10 :     bf_wpack_close_array(pack);
     186           10 : }
     187              : 
     188           10 : void bf_wpack_kv_list(bf_wpack_t *pack, const char *key, const bf_list *value)
     189              : {
     190           10 :     bf_wpack_str(pack, key);
     191           10 :     bf_wpack_list(pack, value);
     192           10 : }
     193              : 
     194           45 : void bf_wpack_open_object(bf_wpack_t *pack, const char *key)
     195              : {
     196           45 :     bf_assert(pack);
     197              : 
     198           45 :     if (key)
     199            1 :         mpack_write_cstr(&pack->writer, key);
     200              : 
     201           45 :     mpack_build_map(&pack->writer);
     202           45 : }
     203              : 
     204           45 : void bf_wpack_close_object(bf_wpack_t *pack)
     205              : {
     206           45 :     bf_assert(pack);
     207              : 
     208           45 :     mpack_complete_map(&pack->writer);
     209           45 : }
     210              : 
     211           13 : void bf_wpack_open_array(bf_wpack_t *pack, const char *key)
     212              : {
     213           13 :     bf_assert(pack);
     214              : 
     215           13 :     if (key)
     216            3 :         mpack_write_cstr(&pack->writer, key);
     217              : 
     218           13 :     mpack_build_array(&pack->writer);
     219           13 : }
     220              : 
     221           13 : void bf_wpack_close_array(bf_wpack_t *pack)
     222              : {
     223           13 :     bf_assert(pack);
     224              : 
     225           13 :     mpack_complete_array(&pack->writer);
     226           13 : }
     227              : 
     228              : struct bf_rpack
     229              : {
     230              :     const void *data;
     231              :     size_t data_len;
     232              : 
     233              :     mpack_tree_t tree;
     234              :     mpack_node_t root;
     235              : };
     236              : 
     237            8 : int bf_rpack_new(bf_rpack_t **pack, const void *data, size_t data_len)
     238              : {
     239            8 :     _free_bf_rpack_ bf_rpack_t *_pack = NULL;
     240              :     mpack_error_t error;
     241              : 
     242            8 :     bf_assert(pack);
     243              : 
     244            8 :     _pack = calloc(1, sizeof(*_pack));
     245            8 :     if (!_pack)
     246              :         return -ENOMEM;
     247              : 
     248            8 :     _pack->data = data;
     249            8 :     _pack->data_len = data_len;
     250              : 
     251            8 :     mpack_tree_init_data(&_pack->tree, data, data_len);
     252              : 
     253            8 :     mpack_tree_parse(&_pack->tree);
     254            8 :     error = mpack_tree_error(&_pack->tree);
     255            8 :     if (error != mpack_ok) {
     256            0 :         return bf_err_r(-EINVAL, "failed to parse bf_rpack_t data: %s",
     257              :                         mpack_error_to_string(error));
     258              :     }
     259              : 
     260            8 :     _pack->root = mpack_tree_root(&_pack->tree);
     261              : 
     262            8 :     *pack = TAKE_PTR(_pack);
     263              : 
     264            8 :     return 0;
     265              : }
     266              : 
     267           16 : void bf_rpack_free(bf_rpack_t **pack)
     268              : {
     269              :     bf_rpack_t *_pack;
     270              : 
     271           16 :     bf_assert(pack);
     272              : 
     273           16 :     _pack = *pack;
     274           16 :     if (!_pack)
     275              :         return;
     276              : 
     277            8 :     mpack_tree_destroy(&_pack->tree);
     278              :     freep((void *)pack);
     279              : }
     280              : 
     281              : #define MP_NODE(node) (*(mpack_node_t *)&(node))
     282              : #define BF_NODE(node) (*(bf_rpack_node_t *)(mpack_node_t[]) {node})
     283              : 
     284              : _Static_assert(sizeof(bf_rpack_node_t) >= sizeof(mpack_node_t),
     285              :                "bf_rpack_node_t too small for mpack_node_t");
     286              : 
     287            8 : bf_rpack_node_t bf_rpack_root(const bf_rpack_t *pack)
     288              : {
     289            8 :     return BF_NODE(pack->root);
     290              : }
     291              : 
     292          126 : size_t bf_rpack_array_count(bf_rpack_node_t node)
     293              : {
     294          126 :     return mpack_node_array_length(MP_NODE(node));
     295              : }
     296              : 
     297            2 : bool bf_rpack_is_nil(bf_rpack_node_t node)
     298              : {
     299            2 :     if (mpack_node_error(MP_NODE(node)) != mpack_ok)
     300              :         return false;
     301              : 
     302            2 :     return mpack_node_type(MP_NODE(node)) == mpack_type_nil;
     303              : }
     304              : 
     305            0 : bool bf_rpack_is_array(bf_rpack_node_t node)
     306              : {
     307            0 :     if (mpack_node_error(MP_NODE(node)) != mpack_ok)
     308              :         return false;
     309              : 
     310            0 :     return mpack_node_type(MP_NODE(node)) == mpack_type_array;
     311              : }
     312              : 
     313           50 : bf_rpack_node_t bf_rpack_array_value_at(bf_rpack_node_t node, size_t index)
     314              : {
     315           50 :     return BF_NODE(mpack_node_array_at(MP_NODE(node), index));
     316              : }
     317              : 
     318            0 : bool bf_rpack_kv_contains(bf_rpack_node_t node, const char *key)
     319              : {
     320            0 :     return mpack_node_map_contains_cstr(MP_NODE(node), key);
     321              : }
     322              : 
     323          172 : int bf_rpack_kv_node(bf_rpack_node_t node, const char *key,
     324              :                      bf_rpack_node_t *child)
     325              : {
     326          172 :     mpack_node_t _node = MP_NODE(node);
     327              : 
     328          172 :     bf_assert(key);
     329          172 :     bf_assert(child);
     330              : 
     331          172 :     if (mpack_node_error(_node) != mpack_ok)
     332              :         return -EINVAL;
     333              : 
     334          172 :     if (mpack_node_type(_node) != mpack_type_map)
     335              :         return -EDOM;
     336              : 
     337          172 :     if (!mpack_node_map_contains_cstr(_node, key))
     338              :         return -ENOENT;
     339              : 
     340          172 :     *child = BF_NODE(mpack_node_map_cstr(_node, key));
     341              : 
     342          172 :     return 0;
     343              : }
     344              : 
     345           61 : int bf_rpack_int(bf_rpack_node_t node, int *value)
     346              : {
     347           61 :     mpack_node_t _node = MP_NODE(node);
     348              :     int _value;
     349              : 
     350              :     /* Signed integere are sometimes stored as unsigned integer for optimization
     351              :      * purposes. While not ideal, we should allow the node to be an unsigned
     352              :      * integer. */
     353          122 :     if (mpack_node_type(_node) != mpack_type_int &&
     354           61 :         mpack_node_type(_node) != mpack_type_uint)
     355              :         return -EDOM;
     356              : 
     357           61 :     _value = mpack_node_int(_node);
     358           61 :     if (mpack_node_error(_node) != mpack_ok)
     359              :         return -EINVAL;
     360              : 
     361           61 :     *value = _value;
     362              : 
     363           61 :     return 0;
     364              : }
     365              : 
     366           58 : int bf_rpack_kv_int(bf_rpack_node_t node, const char *key, int *value)
     367              : {
     368              :     bf_rpack_node_t child;
     369              :     int r;
     370              : 
     371           58 :     r = bf_rpack_kv_node(node, key, &child);
     372           58 :     if (r)
     373              :         return r;
     374              : 
     375           58 :     return bf_rpack_int(child, value);
     376              : }
     377              : 
     378            0 : int bf_rpack_uint(bf_rpack_node_t node, unsigned int *value)
     379              : {
     380            0 :     mpack_node_t _node = MP_NODE(node);
     381              :     unsigned int _value;
     382              : 
     383            0 :     if (mpack_node_error(_node) != mpack_ok)
     384              :         return -EINVAL;
     385              : 
     386            0 :     if (mpack_node_type(_node) != mpack_type_uint)
     387              :         return -EDOM;
     388              : 
     389            0 :     _value = mpack_node_uint(_node);
     390            0 :     if (mpack_node_error(_node) != mpack_ok)
     391              :         return -EINVAL;
     392              : 
     393            0 :     *value = _value;
     394              : 
     395            0 :     return 0;
     396              : }
     397              : 
     398            0 : int bf_rpack_kv_uint(bf_rpack_node_t node, const char *key, unsigned int *value)
     399              : {
     400              :     bf_rpack_node_t child;
     401              :     int r;
     402              : 
     403            0 :     r = bf_rpack_kv_node(node, key, &child);
     404            0 :     if (r)
     405              :         return r;
     406              : 
     407            0 :     return bf_rpack_uint(child, value);
     408              : }
     409              : 
     410            5 : int bf_rpack_u8(bf_rpack_node_t node, uint8_t *value)
     411              : {
     412            5 :     mpack_node_t _node = MP_NODE(node);
     413              :     uint8_t _value;
     414              : 
     415            5 :     if (mpack_node_error(_node) != mpack_ok)
     416              :         return -EINVAL;
     417              : 
     418            5 :     if (mpack_node_type(_node) != mpack_type_uint)
     419              :         return -EDOM;
     420              : 
     421            5 :     _value = mpack_node_u8(_node);
     422            5 :     if (mpack_node_error(_node) != mpack_ok)
     423              :         return -EINVAL;
     424              : 
     425            5 :     *value = _value;
     426              : 
     427            5 :     return 0;
     428              : }
     429              : 
     430            5 : int bf_rpack_kv_u8(bf_rpack_node_t node, const char *key, uint8_t *value)
     431              : {
     432              :     bf_rpack_node_t child;
     433              :     int r;
     434              : 
     435            5 :     r = bf_rpack_kv_node(node, key, &child);
     436            5 :     if (r)
     437              :         return r;
     438              : 
     439            5 :     return bf_rpack_u8(child, value);
     440              : }
     441              : 
     442            0 : int bf_rpack_u16(bf_rpack_node_t node, uint16_t *value)
     443              : {
     444            0 :     mpack_node_t _node = MP_NODE(node);
     445              :     uint16_t _value;
     446              : 
     447            0 :     if (mpack_node_error(_node) != mpack_ok)
     448              :         return -EINVAL;
     449              : 
     450            0 :     if (mpack_node_type(_node) != mpack_type_uint)
     451              :         return -EDOM;
     452              : 
     453            0 :     _value = mpack_node_u16(_node);
     454            0 :     if (mpack_node_error(_node) != mpack_ok)
     455              :         return -EINVAL;
     456              : 
     457            0 :     *value = _value;
     458              : 
     459            0 :     return 0;
     460              : }
     461              : 
     462            0 : int bf_rpack_kv_u16(bf_rpack_node_t node, const char *key, uint16_t *value)
     463              : {
     464              :     bf_rpack_node_t child;
     465              :     int r;
     466              : 
     467            0 :     r = bf_rpack_kv_node(node, key, &child);
     468            0 :     if (r)
     469              :         return r;
     470              : 
     471            0 :     return bf_rpack_u16(child, value);
     472              : }
     473              : 
     474            5 : int bf_rpack_u32(bf_rpack_node_t node, uint32_t *value)
     475              : {
     476            5 :     mpack_node_t _node = MP_NODE(node);
     477              :     uint32_t _value;
     478              : 
     479            5 :     if (mpack_node_error(_node) != mpack_ok)
     480              :         return -EINVAL;
     481              : 
     482            5 :     if (mpack_node_type(_node) != mpack_type_uint)
     483              :         return -EDOM;
     484              : 
     485            5 :     _value = mpack_node_u32(_node);
     486            5 :     if (mpack_node_error(_node) != mpack_ok)
     487              :         return -EINVAL;
     488              : 
     489            5 :     *value = _value;
     490              : 
     491            5 :     return 0;
     492              : }
     493              : 
     494            5 : int bf_rpack_kv_u32(bf_rpack_node_t node, const char *key, uint32_t *value)
     495              : {
     496              :     bf_rpack_node_t child;
     497              :     int r;
     498              : 
     499            5 :     r = bf_rpack_kv_node(node, key, &child);
     500            5 :     if (r)
     501              :         return r;
     502              : 
     503            5 :     return bf_rpack_u32(child, value);
     504              : }
     505              : 
     506           39 : int bf_rpack_u64(bf_rpack_node_t node, uint64_t *value)
     507              : {
     508           39 :     mpack_node_t _node = MP_NODE(node);
     509              :     uint64_t _value;
     510              : 
     511           39 :     if (mpack_node_error(_node) != mpack_ok)
     512              :         return -EINVAL;
     513              : 
     514           39 :     if (mpack_node_type(_node) != mpack_type_uint)
     515              :         return -EDOM;
     516              : 
     517           39 :     _value = mpack_node_u64(_node);
     518           39 :     if (mpack_node_error(_node) != mpack_ok)
     519              :         return -EINVAL;
     520              : 
     521           39 :     *value = _value;
     522              : 
     523           39 :     return 0;
     524              : }
     525              : 
     526           39 : int bf_rpack_kv_u64(bf_rpack_node_t node, const char *key, uint64_t *value)
     527              : {
     528              :     bf_rpack_node_t child;
     529              :     int r;
     530              : 
     531           39 :     r = bf_rpack_kv_node(node, key, &child);
     532           39 :     if (r)
     533              :         return r;
     534              : 
     535           39 :     return bf_rpack_u64(child, value);
     536              : }
     537              : 
     538           11 : int bf_rpack_str(bf_rpack_node_t node, char **value)
     539              : {
     540           11 :     mpack_node_t _node = MP_NODE(node);
     541              :     _cleanup_free_ char *_value = NULL;
     542              : 
     543           11 :     if (mpack_node_error(_node) != mpack_ok)
     544              :         return -EINVAL;
     545              : 
     546           11 :     if (mpack_node_type(_node) != mpack_type_str)
     547              :         return -EDOM;
     548              : 
     549           11 :     _value = mpack_node_cstr_alloc(_node, mpack_node_strlen(_node) + 1);
     550           11 :     if (mpack_node_error(_node) != mpack_ok)
     551              :         return -EINVAL;
     552              : 
     553           11 :     *value = TAKE_PTR(_value);
     554              : 
     555           11 :     return 0;
     556              : }
     557              : 
     558           11 : int bf_rpack_kv_str(bf_rpack_node_t node, const char *key, char **value)
     559              : {
     560              :     bf_rpack_node_t child;
     561              :     int r;
     562              : 
     563           11 :     bf_assert(key);
     564           11 :     bf_assert(value);
     565              : 
     566           11 :     r = bf_rpack_kv_node(node, key, &child);
     567           11 :     if (r)
     568              :         return r;
     569              : 
     570           11 :     return bf_rpack_str(child, value);
     571              : }
     572              : 
     573            5 : int bf_rpack_bool(bf_rpack_node_t node, bool *value)
     574              : {
     575            5 :     mpack_node_t _node = MP_NODE(node);
     576              :     bool _value;
     577              : 
     578            5 :     if (mpack_node_error(_node) != mpack_ok)
     579              :         return -EINVAL;
     580              : 
     581            5 :     if (mpack_node_type(_node) != mpack_type_bool)
     582              :         return -EDOM;
     583              : 
     584            5 :     _value = mpack_node_bool(_node);
     585            5 :     if (mpack_node_error(_node) != mpack_ok)
     586              :         return -EINVAL;
     587              : 
     588            5 :     *value = _value;
     589              : 
     590            5 :     return 0;
     591              : }
     592              : 
     593            5 : int bf_rpack_kv_bool(bf_rpack_node_t node, const char *key, bool *value)
     594              : {
     595              :     bf_rpack_node_t child;
     596              :     int r;
     597              : 
     598            5 :     r = bf_rpack_kv_node(node, key, &child);
     599            5 :     if (r)
     600              :         return r;
     601              : 
     602            5 :     return bf_rpack_bool(child, value);
     603              : }
     604              : 
     605           36 : int bf_rpack_bin(bf_rpack_node_t node, const void **data, size_t *data_len)
     606              : {
     607           36 :     mpack_node_t _node = MP_NODE(node);
     608              :     const void *_data;
     609              :     size_t _data_len;
     610              : 
     611           36 :     if (mpack_node_error(_node) != mpack_ok)
     612              :         return -EINVAL;
     613              : 
     614           36 :     if (mpack_node_type(_node) != mpack_type_bin)
     615              :         return -EDOM;
     616              : 
     617           36 :     _data_len = mpack_node_bin_size(_node);
     618           36 :     _data = mpack_node_bin_data(_node);
     619           36 :     if (mpack_node_error(_node) != mpack_ok)
     620              :         return -EINVAL;
     621              : 
     622           36 :     *data = _data;
     623           36 :     *data_len = _data_len;
     624              : 
     625           36 :     return 0;
     626              : }
     627              : 
     628           33 : int bf_rpack_kv_bin(bf_rpack_node_t node, const char *key, const void **data,
     629              :                     size_t *data_len)
     630              : {
     631              :     bf_rpack_node_t child;
     632              :     int r;
     633              : 
     634           33 :     r = bf_rpack_kv_node(node, key, &child);
     635           33 :     if (r)
     636              :         return r;
     637              : 
     638           33 :     return bf_rpack_bin(child, data, data_len);
     639              : }
     640              : 
     641            1 : int bf_rpack_kv_obj(bf_rpack_node_t node, const char *key,
     642              :                     bf_rpack_node_t *child)
     643              : {
     644              :     bf_rpack_node_t _child;
     645              :     int r;
     646              : 
     647            1 :     bf_assert(key);
     648            1 :     bf_assert(child);
     649              : 
     650            1 :     r = bf_rpack_kv_node(node, key, &_child);
     651            1 :     if (r)
     652              :         return r;
     653              : 
     654            1 :     if (mpack_node_type(MP_NODE(_child)) != mpack_type_map)
     655              :         return -EDOM;
     656              : 
     657            1 :     *child = _child;
     658              : 
     659            1 :     return 0;
     660              : }
     661              : 
     662           13 : int bf_rpack_kv_array(bf_rpack_node_t node, const char *key,
     663              :                       bf_rpack_node_t *child)
     664              : {
     665              :     bf_rpack_node_t _child;
     666              :     int r;
     667              : 
     668           13 :     bf_assert(key);
     669           13 :     bf_assert(child);
     670              : 
     671           13 :     r = bf_rpack_kv_node(node, key, &_child);
     672           13 :     if (r)
     673              :         return r;
     674              : 
     675           13 :     if (mpack_node_type(MP_NODE(_child)) != mpack_type_array)
     676              :         return -EDOM;
     677              : 
     678           13 :     *child = _child;
     679              : 
     680           13 :     return 0;
     681              : }
        

Generated by: LCOV version 2.0-1