LCOV - code coverage report
Current view: top level - ballet/pb - fd_pb_gen.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 202 252 80.2 %
Date: 2026-11-11 12:40:43 Functions: 25 28 89.3 %

          Line data    Source code
       1             : #include "fd_pb_gen.h"
       2             : 
       3             : uchar *
       4             : fd_pb_encode( fd_pb_msgdesc_t const * desc,
       5             :               void const *            msg,
       6             :               uchar *                 out,
       7      130186 :               ulong *                 out_sz ) {
       8      130186 :   fd_pb_encoder_t enc[1];
       9      130186 :   fd_pb_encoder_init( enc, out, *out_sz );
      10      130186 :   if( FD_UNLIKELY( !desc->encode( enc, msg ) ) ) return NULL;
      11      130186 :   *out_sz = fd_pb_encoder_out_sz( enc );
      12      130186 :   fd_pb_encoder_fini( enc );
      13      130186 :   return out;
      14      130186 : }
      15             : 
      16             : void *
      17             : fd_pb_decode( fd_pb_msgdesc_t const * desc,
      18             :               void *                  msg,
      19             :               void const *            in,
      20             :               ulong                   in_sz,
      21       71985 :               fd_spad_t *             spad ) {
      22       71985 :   fd_pb_inbuf_t buf[1];
      23       71985 :   fd_pb_inbuf_init( buf, in, in_sz );
      24       71985 :   if( FD_UNLIKELY( !desc->decode( buf, msg, spad ) ) ) return NULL;
      25       71985 :   return msg;
      26       71985 : }
      27             : 
      28             : /* Scalar decoding */
      29             : 
      30             : static int
      31             : dec_varint( fd_pb_tlv_t const * tlv,
      32     4255410 :             ulong *             out ) {
      33     4255410 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_VARINT ) ) return 0;
      34     4255410 :   *out = tlv->varint;
      35     4255410 :   return 1;
      36     4255410 : }
      37             : 
      38             : int
      39      966218 : fd_pb_dec_bool( fd_pb_tlv_t const * tlv, bool * out ) {
      40      966218 :   ulong v;
      41      966218 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      42      966218 :   *out = v!=0UL;
      43      966218 :   return 1;
      44      966218 : }
      45             : 
      46             : int
      47       36249 : fd_pb_dec_int32( fd_pb_tlv_t const * tlv, int * out ) {
      48       36249 :   ulong v;
      49       36249 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      50       36249 :   *out = (int)(uint)v;
      51       36249 :   return 1;
      52       36249 : }
      53             : 
      54             : int
      55      560659 : fd_pb_dec_uint32( fd_pb_tlv_t const * tlv, uint * out ) {
      56      560659 :   ulong v;
      57      560659 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      58      560659 :   if( FD_UNLIKELY( v>UINT_MAX ) ) return 0;
      59      560659 :   *out = (uint)v;
      60      560659 :   return 1;
      61      560659 : }
      62             : 
      63             : int
      64           0 : fd_pb_dec_sint32( fd_pb_tlv_t const * tlv, int * out ) {
      65           0 :   ulong v;
      66           0 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      67           0 :   long s = fd_long_zz_dec( v );
      68           0 :   if( FD_UNLIKELY( s<INT_MIN || s>INT_MAX ) ) return 0;
      69           0 :   *out = (int)s;
      70           0 :   return 1;
      71           0 : }
      72             : 
      73             : int
      74        1732 : fd_pb_dec_int64( fd_pb_tlv_t const * tlv, long * out ) {
      75        1732 :   ulong v;
      76        1732 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      77        1732 :   *out = (long)v;
      78        1732 :   return 1;
      79        1732 : }
      80             : 
      81             : int
      82     2943992 : fd_pb_dec_uint64( fd_pb_tlv_t const * tlv, ulong * out ) {
      83     2943992 :   return dec_varint( tlv, out );
      84     2943992 : }
      85             : 
      86             : int
      87           0 : fd_pb_dec_sint64( fd_pb_tlv_t const * tlv, long * out ) {
      88           0 :   ulong v;
      89           0 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      90           0 :   *out = fd_long_zz_dec( v );
      91           0 :   return 1;
      92           0 : }
      93             : 
      94             : int
      95          44 : fd_pb_dec_fixed32( fd_pb_tlv_t const * tlv, uint * out ) {
      96          44 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_I32 ) ) return 0;
      97          44 :   *out = tlv->i32;
      98          44 :   return 1;
      99          44 : }
     100             : 
     101             : int
     102    10100157 : fd_pb_dec_fixed64( fd_pb_tlv_t const * tlv, ulong * out ) {
     103    10100157 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_I64 ) ) return 0;
     104    10100157 :   *out = tlv->i64;
     105    10100157 :   return 1;
     106    10100157 : }
     107             : 
     108             : int
     109           0 : fd_pb_dec_float( fd_pb_tlv_t const * tlv, float * out ) {
     110           0 :   union { uint u; float f; } cast;
     111           0 :   if( FD_UNLIKELY( !fd_pb_dec_fixed32( tlv, &cast.u ) ) ) return 0;
     112           0 :   *out = cast.f;
     113           0 :   return 1;
     114           0 : }
     115             : 
     116             : int
     117        3031 : fd_pb_dec_double( fd_pb_tlv_t const * tlv, double * out ) {
     118        3031 :   union { ulong u; double d; } cast;
     119        3031 :   if( FD_UNLIKELY( !fd_pb_dec_fixed64( tlv, &cast.u ) ) ) return 0;
     120        3031 :   *out = cast.d;
     121        3031 :   return 1;
     122        3031 : }
     123             : 
     124             : /* Repeated fields */
     125             : 
     126             : void *
     127             : fd_pb_dec_grow( fd_spad_t * spad,
     128             :                 void *      arr,
     129             :                 uint *      cnt,
     130             :                 ulong       ele_align,
     131    11324467 :                 ulong       ele_sz ) {
     132    11324467 :   uint n = *cnt;
     133    11324467 :   if( FD_UNLIKELY( n==UINT_MAX ) ) return NULL;
     134    11324467 :   void * base;
     135    11324467 :   fd_memcpy( &base, arr, sizeof(void *) );
     136             :   /* Capacity is the next power of two of n (geometric growth) */
     137    11498663 :   if( !n || fd_uint_is_pow2( n ) ) {
     138     1411120 :     ulong cap = n ? 2UL*n : 1UL;
     139     1411120 :     if( FD_UNLIKELY( fd_spad_alloc_max( spad, ele_align )<cap*ele_sz ) ) return NULL;
     140     1411120 :     void * p = fd_spad_alloc( spad, ele_align, cap*ele_sz );
     141     1411120 :     if( n ) fd_memcpy( p, base, n*ele_sz );
     142     1411120 :     base = p;
     143     1411120 :     fd_memcpy( arr, &base, sizeof(void *) );
     144     1411120 :   }
     145    11324467 :   uchar * ele = (uchar *)base + n*ele_sz;
     146    11324467 :   memset( ele, 0, ele_sz );
     147    11324467 :   *cnt = n+1U;
     148    11324467 :   return ele;
     149    11324467 : }
     150             : 
     151             : static ulong
     152       93169 : type_sz( int type ) {
     153       93169 :   switch( type ) {
     154        1007 :   case FD_PB_GEN_BOOL:    return sizeof(bool);
     155           0 :   case FD_PB_GEN_INT32:
     156       25447 :   case FD_PB_GEN_UINT32:
     157       25447 :   case FD_PB_GEN_SINT32:
     158       25447 :   case FD_PB_GEN_FIXED32: return 4UL;
     159       66753 :   default:                return 8UL;
     160       93169 :   }
     161       93169 : }
     162             : 
     163             : static int
     164             : dec_scalar( fd_pb_tlv_t const * tlv,
     165             :             int                 type,
     166     9803039 :             void *              out ) {
     167     9803039 :   switch( type ) {
     168      140492 :   case FD_PB_GEN_BOOL:    return fd_pb_dec_bool   ( tlv, out );
     169           0 :   case FD_PB_GEN_INT32:   return fd_pb_dec_int32  ( tlv, out );
     170      108518 :   case FD_PB_GEN_UINT32:  return fd_pb_dec_uint32 ( tlv, out );
     171           0 :   case FD_PB_GEN_SINT32:  return fd_pb_dec_sint32 ( tlv, out );
     172           0 :   case FD_PB_GEN_INT64:   return fd_pb_dec_int64  ( tlv, out );
     173           0 :   case FD_PB_GEN_UINT64:  return fd_pb_dec_uint64 ( tlv, out );
     174           0 :   case FD_PB_GEN_SINT64:  return fd_pb_dec_sint64 ( tlv, out );
     175           0 :   case FD_PB_GEN_FIXED32: return fd_pb_dec_fixed32( tlv, out );
     176     9683919 :   case FD_PB_GEN_FIXED64: return fd_pb_dec_fixed64( tlv, out );
     177           0 :   default:                return 0;
     178     9803039 :   }
     179     9803039 : }
     180             : 
     181             : static uint
     182       93077 : type_wire( int type ) {
     183       93077 :   switch( type ) {
     184           0 :   case FD_PB_GEN_FIXED32: return FD_PB_WIRE_TYPE_I32;
     185       66629 :   case FD_PB_GEN_FIXED64: return FD_PB_WIRE_TYPE_I64;
     186       26343 :   default:                return FD_PB_WIRE_TYPE_VARINT;
     187       93077 :   }
     188       93077 : }
     189             : 
     190             : int
     191             : fd_pb_dec_repeated( fd_pb_inbuf_t *     in,
     192             :                     fd_pb_tlv_t const * tlv,
     193             :                     fd_spad_t *         spad,
     194             :                     int                 type,
     195             :                     void *              arr,
     196       93087 :                     uint *              cnt ) {
     197       93087 :   ulong ele_sz = type_sz( type );
     198       93087 :   if( tlv->wire_type!=FD_PB_WIRE_TYPE_LEN ) {
     199           0 :     void * ele = fd_pb_dec_grow( spad, arr, cnt, ele_sz, ele_sz );
     200           0 :     if( FD_UNLIKELY( !ele ) ) return 0;
     201           0 :     return dec_scalar( tlv, type, ele );
     202           0 :   }
     203             : 
     204             :   /* Packed */
     205       93087 :   fd_pb_inbuf_t sub[1];
     206       93087 :   if( FD_UNLIKELY( !fd_pb_tlv_submsg( in, tlv, sub ) ) ) return 0;
     207       93087 :   in->cur = sub->end;
     208       93087 :   fd_pb_tlv_t vtlv[1] = {{ .wire_type = type_wire( type ), .field_id = tlv->field_id }};
     209     9348578 :   while( fd_pb_inbuf_sz( sub ) ) {
     210     9179004 :     switch( vtlv->wire_type ) {
     211      246547 :     case FD_PB_WIRE_TYPE_VARINT:
     212      246547 :       if( FD_UNLIKELY( !fd_pb_read_varint( sub, &vtlv->varint ) ) ) return 0;
     213      246547 :       break;
     214      246547 :     case FD_PB_WIRE_TYPE_I32:
     215           0 :       if( FD_UNLIKELY( fd_pb_inbuf_sz( sub )<4UL ) ) return 0;
     216           0 :       vtlv->varint = 0UL;
     217           0 :       vtlv->i32    = FD_LOAD( uint, sub->cur );
     218           0 :       sub->cur    += 4UL;
     219           0 :       break;
     220     9159806 :     case FD_PB_WIRE_TYPE_I64:
     221     9159806 :       if( FD_UNLIKELY( fd_pb_inbuf_sz( sub )<8UL ) ) return 0;
     222     9159806 :       vtlv->i64    = FD_LOAD( ulong, sub->cur );
     223     9159806 :       sub->cur    += 8UL;
     224     9159806 :       break;
     225     9179004 :     }
     226     9255491 :     void * ele = fd_pb_dec_grow( spad, arr, cnt, ele_sz, ele_sz );
     227     9255491 :     if( FD_UNLIKELY( !ele ) ) return 0;
     228     9255491 :     if( FD_UNLIKELY( !dec_scalar( vtlv, type, ele ) ) ) return 0;
     229     9255491 :   }
     230      169574 :   return 1;
     231       93087 : }
     232             : 
     233             : /* Length-delimited fields */
     234             : 
     235             : int
     236             : fd_pb_dec_submsg( fd_pb_inbuf_t *         in,
     237             :                   fd_pb_tlv_t const *     tlv,
     238             :                   fd_spad_t *             spad,
     239             :                   fd_pb_msgdesc_t const * desc,
     240     3255237 :                   void *                  msg ) {
     241     3255237 :   fd_pb_inbuf_t sub[1];
     242     3255237 :   if( FD_UNLIKELY( !fd_pb_tlv_submsg( in, tlv, sub ) ) ) return 0;
     243     3255237 :   in->cur = sub->end;
     244     3255237 :   return desc->decode( sub, msg, spad );
     245     3255237 : }
     246             : 
     247             : int
     248             : fd_pb_dec_bytes_ptr( fd_pb_inbuf_t *        in,
     249             :                      fd_pb_tlv_t const *    tlv,
     250             :                      fd_spad_t *            spad,
     251     1025743 :                      fd_pb_bytes_array_t ** out ) {
     252     1025743 :   uchar const * data = fd_pb_tlv_bytes( in, tlv );
     253     1025743 :   if( FD_UNLIKELY( !data || tlv->len>UINT_MAX ) ) return 0;
     254     1025743 :   ulong sz = FD_PB_BYTES_ARRAY_T_ALLOCSIZE( tlv->len );
     255     1025743 :   if( FD_UNLIKELY( fd_spad_alloc_max( spad, alignof(fd_pb_bytes_array_t) )<sz ) ) return 0;
     256     1025743 :   fd_pb_bytes_array_t * arr = fd_spad_alloc( spad, alignof(fd_pb_bytes_array_t), sz );
     257     1025743 :   arr->size = (uint)tlv->len;
     258     1025743 :   fd_memcpy( arr->bytes, data, tlv->len );
     259     1025743 :   *out     = arr;
     260     1025743 :   in->cur += tlv->len;
     261     1025743 :   return 1;
     262     1025743 : }
     263             : 
     264             : int
     265             : fd_pb_dec_bytes_fixed( fd_pb_inbuf_t *     in,
     266             :                        fd_pb_tlv_t const * tlv,
     267             :                        uchar *             out,
     268     3644693 :                        ulong               sz ) {
     269     3644693 :   uchar const * data = fd_pb_tlv_bytes( in, tlv );
     270     3644693 :   if( FD_UNLIKELY( !data ) ) return 0;
     271     3644693 :   if( !tlv->len ) {
     272             :     /* Empty bytes decode as all zeros */
     273           0 :     memset( out, 0, sz );
     274           0 :     return 1;
     275           0 :   }
     276     3644693 :   if( FD_UNLIKELY( tlv->len!=sz ) ) return 0;
     277     3644693 :   fd_memcpy( out, data, sz );
     278     3644693 :   in->cur += sz;
     279     3644693 :   return 1;
     280     3644693 : }
     281             : 
     282             : int
     283             : fd_pb_dec_bytes_static( fd_pb_inbuf_t *     in,
     284             :                         fd_pb_tlv_t const * tlv,
     285             :                         uchar *             out,
     286             :                         uint *              out_sz,
     287        7573 :                         ulong               max ) {
     288        7573 :   uchar const * data = fd_pb_tlv_bytes( in, tlv );
     289        7573 :   if( FD_UNLIKELY( !data || tlv->len>max ) ) return 0;
     290        7573 :   fd_memcpy( out, data, tlv->len );
     291        7573 :   *out_sz  = (uint)tlv->len;
     292        7573 :   in->cur += tlv->len;
     293        7573 :   return 1;
     294        7573 : }
     295             : 
     296             : int
     297             : fd_pb_dec_string_static( fd_pb_inbuf_t *     in,
     298             :                          fd_pb_tlv_t const * tlv,
     299             :                          char *              out,
     300       71530 :                          ulong               max ) {
     301       71530 :   if( FD_UNLIKELY( !fd_pb_tlv_cstr( in, tlv, out, max ) ) ) return 0;
     302       71530 :   in->cur += tlv->len;
     303       71530 :   return 1;
     304       71530 : }
     305             : 
     306             : /* Encoding */
     307             : 
     308             : /* lp_close_compact closes a LEN field opened with fd_pb_lp_open and
     309             :    rewrites the length prefix in its shortest form. */
     310             : 
     311             : static int
     312     1182591 : lp_close_compact( fd_pb_encoder_t * enc ) {
     313     1182591 :   uchar * lp   = enc->buf0 + enc->lp_off[ enc->depth-1U ];
     314     1182591 :   uchar * sub0 = lp + fd_pb_varint32_sz_max;
     315     1182591 :   ulong   sz   = (ulong)( enc->cur - sub0 );
     316     1182591 :   if( FD_UNLIKELY( sz>UINT_MAX ) ) return 0;
     317     1182591 :   fd_pb_lp_close( enc );
     318     1182591 :   uchar   tmp[ 8 ];
     319     1182591 :   ulong   lp_sz = (ulong)( fd_pb_append_varint32( tmp, (uint)sz ) - tmp );
     320     1182591 :   fd_memcpy( lp, tmp, lp_sz );
     321     1182591 :   memmove( lp+lp_sz, sub0, sz );
     322     1182591 :   enc->cur = lp + lp_sz + sz;
     323     1182591 :   return 1;
     324     1182591 : }
     325             : 
     326             : int
     327             : fd_pb_enc_submsg( fd_pb_encoder_t *       enc,
     328             :                   uint                    field_id,
     329             :                   fd_pb_msgdesc_t const * desc,
     330     1178639 :                   void const *            msg ) {
     331     1178639 :   if( FD_UNLIKELY( !fd_pb_submsg_open( enc, field_id ) ) ) return 0;
     332     1178639 :   if( FD_UNLIKELY( !desc->encode( enc, msg ) ) ) return 0;
     333     1178639 :   return lp_close_compact( enc );
     334     1178639 : }
     335             : 
     336             : int
     337             : fd_pb_enc_bytes_ptr( fd_pb_encoder_t *           enc,
     338             :                      uint                        field_id,
     339       17058 :                      fd_pb_bytes_array_t const * bytes ) {
     340       17058 :   static uchar const empty[1];
     341       17058 :   if( !bytes ) return !!fd_pb_push_bytes( enc, field_id, empty, 0UL );
     342       17058 :   return !!fd_pb_push_bytes( enc, field_id, bytes->bytes, bytes->size );
     343       17058 : }
     344             : 
     345             : int
     346             : fd_pb_enc_packed( fd_pb_encoder_t * enc,
     347             :                   uint              field_id,
     348             :                   int               type,
     349             :                   void const *      arr,
     350        2028 :                   ulong             cnt ) {
     351        2028 :   if( !cnt ) return 1;
     352        2016 :   if( FD_UNLIKELY( !fd_pb_lp_open( enc, field_id ) ) ) return 0;
     353      294386 :   for( ulong i=0UL; i<cnt; i++ ) {
     354      292384 :     if( FD_UNLIKELY( fd_pb_encoder_space( enc )<fd_pb_varint64_sz_max ) ) return 0;
     355      292384 :     switch( type ) {
     356      292382 :     case FD_PB_GEN_BOOL:    enc->cur = fd_pb_append_bool   ( enc->cur, ((bool  const *)arr)[i] );        break;
     357           0 :     case FD_PB_GEN_INT32:   enc->cur = fd_pb_append_int64  ( enc->cur, (long)((int const *)arr)[i] );    break;
     358           0 :     case FD_PB_GEN_UINT32:  enc->cur = fd_pb_append_uint32 ( enc->cur, ((uint  const *)arr)[i] );        break;
     359           0 :     case FD_PB_GEN_SINT32:  enc->cur = fd_pb_append_sint32 ( enc->cur, ((int   const *)arr)[i] );        break;
     360           0 :     case FD_PB_GEN_INT64:   enc->cur = fd_pb_append_int64  ( enc->cur, ((long  const *)arr)[i] );        break;
     361           0 :     case FD_PB_GEN_UINT64:  enc->cur = fd_pb_append_uint64 ( enc->cur, ((ulong const *)arr)[i] );        break;
     362           0 :     case FD_PB_GEN_SINT64:  enc->cur = fd_pb_append_sint64 ( enc->cur, ((long  const *)arr)[i] );        break;
     363           0 :     case FD_PB_GEN_FIXED32: enc->cur = fd_pb_append_fixed32( enc->cur, FD_LOAD( uint,  (uchar const *)arr+4UL*i ) ); break;
     364           0 :     case FD_PB_GEN_FIXED64: enc->cur = fd_pb_append_fixed64( enc->cur, FD_LOAD( ulong, (uchar const *)arr+8UL*i ) ); break;
     365           0 :     default: return 0;
     366      292384 :     }
     367      292384 :   }
     368        2002 :   return lp_close_compact( enc );
     369        2016 : }

Generated by: LCOV version 1.14