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

          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           0 :               ulong *                 out_sz ) {
       8           0 :   fd_pb_encoder_t enc[1];
       9           0 :   fd_pb_encoder_init( enc, out, *out_sz );
      10           0 :   if( FD_UNLIKELY( !desc->encode( enc, msg ) ) ) return NULL;
      11           0 :   *out_sz = fd_pb_encoder_out_sz( enc );
      12           0 :   fd_pb_encoder_fini( enc );
      13           0 :   return out;
      14           0 : }
      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           0 :               fd_spad_t *             spad ) {
      22           0 :   fd_pb_inbuf_t buf[1];
      23           0 :   fd_pb_inbuf_init( buf, in, in_sz );
      24           0 :   if( FD_UNLIKELY( !desc->decode( buf, msg, spad ) ) ) return NULL;
      25           0 :   return msg;
      26           0 : }
      27             : 
      28             : /* Scalar decoding */
      29             : 
      30             : static int
      31             : dec_varint( fd_pb_tlv_t const * tlv,
      32           0 :             ulong *             out ) {
      33           0 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_VARINT ) ) return 0;
      34           0 :   *out = tlv->varint;
      35           0 :   return 1;
      36           0 : }
      37             : 
      38             : int
      39           0 : fd_pb_dec_bool( fd_pb_tlv_t const * tlv, bool * out ) {
      40           0 :   ulong v;
      41           0 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      42           0 :   *out = v!=0UL;
      43           0 :   return 1;
      44           0 : }
      45             : 
      46             : int
      47           0 : fd_pb_dec_int32( fd_pb_tlv_t const * tlv, int * out ) {
      48           0 :   ulong v;
      49           0 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      50           0 :   *out = (int)(uint)v;
      51           0 :   return 1;
      52           0 : }
      53             : 
      54             : int
      55           0 : fd_pb_dec_uint32( fd_pb_tlv_t const * tlv, uint * out ) {
      56           0 :   ulong v;
      57           0 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      58           0 :   if( FD_UNLIKELY( v>UINT_MAX ) ) return 0;
      59           0 :   *out = (uint)v;
      60           0 :   return 1;
      61           0 : }
      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           0 : fd_pb_dec_int64( fd_pb_tlv_t const * tlv, long * out ) {
      75           0 :   ulong v;
      76           0 :   if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
      77           0 :   *out = (long)v;
      78           0 :   return 1;
      79           0 : }
      80             : 
      81             : int
      82           0 : fd_pb_dec_uint64( fd_pb_tlv_t const * tlv, ulong * out ) {
      83           0 :   return dec_varint( tlv, out );
      84           0 : }
      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           0 : fd_pb_dec_fixed32( fd_pb_tlv_t const * tlv, uint * out ) {
      96           0 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_I32 ) ) return 0;
      97           0 :   *out = tlv->i32;
      98           0 :   return 1;
      99           0 : }
     100             : 
     101             : int
     102           0 : fd_pb_dec_fixed64( fd_pb_tlv_t const * tlv, ulong * out ) {
     103           0 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_I64 ) ) return 0;
     104           0 :   *out = tlv->i64;
     105           0 :   return 1;
     106           0 : }
     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           0 : fd_pb_dec_double( fd_pb_tlv_t const * tlv, double * out ) {
     118           0 :   union { ulong u; double d; } cast;
     119           0 :   if( FD_UNLIKELY( !fd_pb_dec_fixed64( tlv, &cast.u ) ) ) return 0;
     120           0 :   *out = cast.d;
     121           0 :   return 1;
     122           0 : }
     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           0 :                 ulong       ele_sz ) {
     132           0 :   uint n = *cnt;
     133           0 :   if( FD_UNLIKELY( n==UINT_MAX ) ) return NULL;
     134           0 :   void * base;
     135           0 :   fd_memcpy( &base, arr, sizeof(void *) );
     136             :   /* Capacity is the next power of two of n (geometric growth) */
     137           0 :   if( !n || fd_uint_is_pow2( n ) ) {
     138           0 :     ulong cap = n ? 2UL*n : 1UL;
     139           0 :     if( FD_UNLIKELY( fd_spad_alloc_max( spad, ele_align )<cap*ele_sz ) ) return NULL;
     140           0 :     void * p = fd_spad_alloc( spad, ele_align, cap*ele_sz );
     141           0 :     if( n ) fd_memcpy( p, base, n*ele_sz );
     142           0 :     base = p;
     143           0 :     fd_memcpy( arr, &base, sizeof(void *) );
     144           0 :   }
     145           0 :   uchar * ele = (uchar *)base + n*ele_sz;
     146           0 :   memset( ele, 0, ele_sz );
     147           0 :   *cnt = n+1U;
     148           0 :   return ele;
     149           0 : }
     150             : 
     151             : static ulong
     152           0 : type_sz( int type ) {
     153           0 :   switch( type ) {
     154           0 :   case FD_PB_GEN_BOOL:    return sizeof(bool);
     155           0 :   case FD_PB_GEN_INT32:
     156           0 :   case FD_PB_GEN_UINT32:
     157           0 :   case FD_PB_GEN_SINT32:
     158           0 :   case FD_PB_GEN_FIXED32: return 4UL;
     159           0 :   default:                return 8UL;
     160           0 :   }
     161           0 : }
     162             : 
     163             : static int
     164             : dec_scalar( fd_pb_tlv_t const * tlv,
     165             :             int                 type,
     166           0 :             void *              out ) {
     167           0 :   switch( type ) {
     168           0 :   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           0 :   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           0 :   case FD_PB_GEN_FIXED64: return fd_pb_dec_fixed64( tlv, out );
     177           0 :   default:                return 0;
     178           0 :   }
     179           0 : }
     180             : 
     181             : static uint
     182           0 : type_wire( int type ) {
     183           0 :   switch( type ) {
     184           0 :   case FD_PB_GEN_FIXED32: return FD_PB_WIRE_TYPE_I32;
     185           0 :   case FD_PB_GEN_FIXED64: return FD_PB_WIRE_TYPE_I64;
     186           0 :   default:                return FD_PB_WIRE_TYPE_VARINT;
     187           0 :   }
     188           0 : }
     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           0 :                     uint *              cnt ) {
     197           0 :   ulong ele_sz = type_sz( type );
     198           0 :   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           0 :   fd_pb_inbuf_t sub[1];
     206           0 :   if( FD_UNLIKELY( !fd_pb_tlv_submsg( in, tlv, sub ) ) ) return 0;
     207           0 :   in->cur = sub->end;
     208           0 :   fd_pb_tlv_t vtlv[1] = {{ .wire_type = type_wire( type ), .field_id = tlv->field_id }};
     209           0 :   while( fd_pb_inbuf_sz( sub ) ) {
     210           0 :     switch( vtlv->wire_type ) {
     211           0 :     case FD_PB_WIRE_TYPE_VARINT:
     212           0 :       if( FD_UNLIKELY( !fd_pb_read_varint( sub, &vtlv->varint ) ) ) return 0;
     213           0 :       break;
     214           0 :     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           0 :     case FD_PB_WIRE_TYPE_I64:
     221           0 :       if( FD_UNLIKELY( fd_pb_inbuf_sz( sub )<8UL ) ) return 0;
     222           0 :       vtlv->i64    = FD_LOAD( ulong, sub->cur );
     223           0 :       sub->cur    += 8UL;
     224           0 :       break;
     225           0 :     }
     226           0 :     void * ele = fd_pb_dec_grow( spad, arr, cnt, ele_sz, ele_sz );
     227           0 :     if( FD_UNLIKELY( !ele ) ) return 0;
     228           0 :     if( FD_UNLIKELY( !dec_scalar( vtlv, type, ele ) ) ) return 0;
     229           0 :   }
     230           0 :   return 1;
     231           0 : }
     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           0 :                   void *                  msg ) {
     241           0 :   fd_pb_inbuf_t sub[1];
     242           0 :   if( FD_UNLIKELY( !fd_pb_tlv_submsg( in, tlv, sub ) ) ) return 0;
     243           0 :   in->cur = sub->end;
     244           0 :   return desc->decode( sub, msg, spad );
     245           0 : }
     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           0 :                      fd_pb_bytes_array_t ** out ) {
     252           0 :   uchar const * data = fd_pb_tlv_bytes( in, tlv );
     253           0 :   if( FD_UNLIKELY( !data || tlv->len>UINT_MAX ) ) return 0;
     254           0 :   ulong sz = FD_PB_BYTES_ARRAY_T_ALLOCSIZE( tlv->len );
     255           0 :   if( FD_UNLIKELY( fd_spad_alloc_max( spad, alignof(fd_pb_bytes_array_t) )<sz ) ) return 0;
     256           0 :   fd_pb_bytes_array_t * arr = fd_spad_alloc( spad, alignof(fd_pb_bytes_array_t), sz );
     257           0 :   arr->size = (uint)tlv->len;
     258           0 :   fd_memcpy( arr->bytes, data, tlv->len );
     259           0 :   *out     = arr;
     260           0 :   in->cur += tlv->len;
     261           0 :   return 1;
     262           0 : }
     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           0 :                        ulong               sz ) {
     269           0 :   uchar const * data = fd_pb_tlv_bytes( in, tlv );
     270           0 :   if( FD_UNLIKELY( !data ) ) return 0;
     271           0 :   if( !tlv->len ) {
     272             :     /* Empty bytes decode as all zeros */
     273           0 :     memset( out, 0, sz );
     274           0 :     return 1;
     275           0 :   }
     276           0 :   if( FD_UNLIKELY( tlv->len!=sz ) ) return 0;
     277           0 :   fd_memcpy( out, data, sz );
     278           0 :   in->cur += sz;
     279           0 :   return 1;
     280           0 : }
     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           0 :                         ulong               max ) {
     288           0 :   uchar const * data = fd_pb_tlv_bytes( in, tlv );
     289           0 :   if( FD_UNLIKELY( !data || tlv->len>max ) ) return 0;
     290           0 :   fd_memcpy( out, data, tlv->len );
     291           0 :   *out_sz  = (uint)tlv->len;
     292           0 :   in->cur += tlv->len;
     293           0 :   return 1;
     294           0 : }
     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           0 :                          ulong               max ) {
     301           0 :   if( FD_UNLIKELY( !fd_pb_tlv_cstr( in, tlv, out, max ) ) ) return 0;
     302           0 :   in->cur += tlv->len;
     303           0 :   return 1;
     304           0 : }
     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           0 : lp_close_compact( fd_pb_encoder_t * enc ) {
     313           0 :   uchar * lp   = enc->buf0 + enc->lp_off[ enc->depth-1U ];
     314           0 :   uchar * sub0 = lp + fd_pb_varint32_sz_max;
     315           0 :   ulong   sz   = (ulong)( enc->cur - sub0 );
     316           0 :   if( FD_UNLIKELY( sz>UINT_MAX ) ) return 0;
     317           0 :   fd_pb_lp_close( enc );
     318           0 :   uchar   tmp[ 8 ];
     319           0 :   ulong   lp_sz = (ulong)( fd_pb_append_varint32( tmp, (uint)sz ) - tmp );
     320           0 :   fd_memcpy( lp, tmp, lp_sz );
     321           0 :   memmove( lp+lp_sz, sub0, sz );
     322           0 :   enc->cur = lp + lp_sz + sz;
     323           0 :   return 1;
     324           0 : }
     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           0 :                   void const *            msg ) {
     331           0 :   if( FD_UNLIKELY( !fd_pb_submsg_open( enc, field_id ) ) ) return 0;
     332           0 :   if( FD_UNLIKELY( !desc->encode( enc, msg ) ) ) return 0;
     333           0 :   return lp_close_compact( enc );
     334           0 : }
     335             : 
     336             : int
     337             : fd_pb_enc_bytes_ptr( fd_pb_encoder_t *           enc,
     338             :                      uint                        field_id,
     339           0 :                      fd_pb_bytes_array_t const * bytes ) {
     340           0 :   static uchar const empty[1];
     341           0 :   if( !bytes ) return !!fd_pb_push_bytes( enc, field_id, empty, 0UL );
     342           0 :   return !!fd_pb_push_bytes( enc, field_id, bytes->bytes, bytes->size );
     343           0 : }
     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           0 :                   ulong             cnt ) {
     351           0 :   if( !cnt ) return 1;
     352           0 :   if( FD_UNLIKELY( !fd_pb_lp_open( enc, field_id ) ) ) return 0;
     353           0 :   for( ulong i=0UL; i<cnt; i++ ) {
     354           0 :     if( FD_UNLIKELY( fd_pb_encoder_space( enc )<fd_pb_varint64_sz_max ) ) return 0;
     355           0 :     switch( type ) {
     356           0 :     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           0 :     }
     367           0 :   }
     368           0 :   return lp_close_compact( enc );
     369           0 : }

Generated by: LCOV version 1.14