LCOV - code coverage report
Current view: top level - ballet/pb - fd_pb_tokenize.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 30 58 51.7 %
Date: 2026-11-11 12:40:43 Functions: 16 352 4.5 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_pb_fd_pb_tokenize_h
       2             : #define HEADER_fd_src_ballet_pb_fd_pb_tokenize_h
       3             : 
       4             : /* fd_pb_tokenize.h provides an API to iterate over tokens in Protobuf
       5             :    wire format.  It can be used to deserialize Protobuf. */
       6             : 
       7             : #include "fd_pb_wire.h"
       8             : #include "../base58/fd_base58.h"
       9             : 
      10             : struct fd_pb_inbuf {
      11             :   uchar const * cur;
      12             :   uchar const * end;
      13             : };
      14             : 
      15             : typedef struct fd_pb_inbuf fd_pb_inbuf_t;
      16             : 
      17             : FD_PROTOTYPES_BEGIN
      18             : 
      19             : static inline fd_pb_inbuf_t *
      20             : fd_pb_inbuf_init( fd_pb_inbuf_t * buf,
      21             :                   void const *    data,
      22       71963 :                   ulong           data_sz ) {
      23       71963 :   buf->cur = data;
      24       71963 :   buf->end = buf->cur + data_sz;
      25       71963 :   return buf;
      26       71963 : }
      27             : 
      28             : static inline ulong
      29    32279713 : fd_pb_inbuf_sz( fd_pb_inbuf_t const * buf ) {
      30    32279713 :   return (ulong)( buf->end - buf->cur );
      31    32279713 : }
      32             : 
      33             : static inline void
      34             : fd_pb_inbuf_skip( fd_pb_inbuf_t * buf,
      35           0 :                   ulong           sz ) {
      36           0 :   FD_CHECK_CRIT( sz<=fd_pb_inbuf_sz( buf ), "Attempt to skip past end of buffer" );
      37           0 :   buf->cur += sz;
      38           0 : }
      39             : 
      40             : FD_PROTOTYPES_END
      41             : 
      42             : struct fd_pb_tlv {
      43             :   uint wire_type; /* FD_PB_WIRE_TYPE_* */
      44             :   uint field_id;
      45             : 
      46             :   union {
      47             :     ulong varint;
      48             :     ulong i64;
      49             :     ulong len;
      50             :     uint  i32;
      51             :   };
      52             : };
      53             : 
      54             : typedef struct fd_pb_tlv fd_pb_tlv_t;
      55             : 
      56             : FD_PROTOTYPES_BEGIN
      57             : 
      58             : /* fd_pb_read_varint reads a base-128 varint of up to 10 bytes.  On
      59             :    success, stores the value to *out, advances buf, and returns buf.  On
      60             :    failure (EOF, overflow), returns NULL without advancing buf. */
      61             : 
      62             : fd_pb_inbuf_t *
      63             : fd_pb_read_varint( fd_pb_inbuf_t * buf,
      64             :                    ulong *         out );
      65             : 
      66             : /* fd_pb_tlv_read reads a Protobuf TLV.  This includes a wire type, a
      67             :    field ID, and data.  Data is either a scalar value field, or a length
      68             :    prefix.  Populates *tlv, advances buf, and returns tlv on success.
      69             :    On failure, silently returns NULL without advancing buf.  Reasons for
      70             :    failure include: parse failure, unexpected EOF.
      71             : 
      72             :    buf is advanced as follows:
      73             :    - VARINT, I32, and I64 TLVs are fully consumed
      74             :    - For LEN TLVs, only the length prefix is consumed (the next tlv.len
      75             :      bytes of buf are the value) */
      76             : 
      77             : fd_pb_tlv_t *
      78             : fd_pb_tlv_read( fd_pb_inbuf_t * buf,
      79             :                 fd_pb_tlv_t *   tlv );
      80             : 
      81             : /* fd_pb_tlv_bytes interprets a TLV as a byte array value. */
      82             : 
      83             : static inline uchar const *
      84             : fd_pb_tlv_bytes( fd_pb_inbuf_t const * buf,
      85     4530648 :                  fd_pb_tlv_t const *   tlv ) {
      86     4530648 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_LEN ||
      87     4530648 :                    tlv->len > fd_pb_inbuf_sz( buf ) ) ) {
      88           0 :     return NULL;
      89           0 :   }
      90     4530648 :   return buf->cur;
      91     4530648 : }
      92             : 
      93             : /* fd_pb_tlv_cstr interprets converts a byte array TLV into a NULL-
      94             :    terminated C string.  cstr_max is the cstr buffer size and includes
      95             :    the NULL terminator. */
      96             : 
      97             : static inline char *
      98             : fd_pb_tlv_cstr( fd_pb_inbuf_t const * buf,
      99             :                 fd_pb_tlv_t const *   tlv,
     100             :                 char *                cstr,
     101       71485 :                 ulong                 cstr_max ) {
     102       71485 :   if( FD_UNLIKELY( !cstr_max ||
     103       71485 :                    tlv->wire_type!=FD_PB_WIRE_TYPE_LEN ||
     104       71485 :                    tlv->len > fd_pb_inbuf_sz( buf ) ||
     105       71485 :                    tlv->len > cstr_max-1UL ) ) {
     106           0 :     return NULL;
     107           0 :   }
     108       71485 :   char * p = fd_cstr_init( cstr );
     109       71485 :   p = fd_cstr_append_text( p, (char const *)buf->cur, tlv->len );
     110       71485 :   fd_cstr_fini( p );
     111       71485 :   return cstr;
     112       71485 : }
     113             : 
     114             : /* fd_pb_tlv_base58_32 interprets a TLV as a Base58-encoded 32-byte
     115             :    string. */
     116             : 
     117             : static FD_FN_UNUSED uchar const *
     118             : fd_pb_tlv_base58_32( fd_pb_inbuf_t const * buf,
     119             :                      fd_pb_tlv_t const *   tlv,
     120           0 :                      uchar                 out[ 32 ] ) {
     121           0 :   char str[ FD_BASE58_ENCODED_32_SZ ];
     122           0 :   if( FD_UNLIKELY( !fd_pb_tlv_cstr( buf, tlv, str, sizeof(str) ) ) ) {
     123           0 :     return NULL;
     124           0 :   }
     125           0 :   if( FD_UNLIKELY( !fd_base58_decode_32( str, out ) ) ) {
     126           0 :     return NULL;
     127           0 :   }
     128           0 :   return out;
     129           0 : }
     130             : 
     131             : /* fd_pb_tlv_submsg interprets a TLV as a Protobuf submessage. */
     132             : 
     133             : static FD_FN_UNUSED fd_pb_inbuf_t *
     134             : fd_pb_tlv_submsg( fd_pb_inbuf_t const * buf,
     135             :                   fd_pb_tlv_t const *   tlv,
     136     3359357 :                   fd_pb_inbuf_t *       submsg ) {
     137     3359357 :   if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_LEN ||
     138     3359357 :                    tlv->len > fd_pb_inbuf_sz( buf ) ) ) {
     139           0 :     return NULL;
     140           0 :   }
     141     3359357 :   submsg->cur = buf->cur;
     142     3359357 :   submsg->end = submsg->cur + tlv->len;
     143     3359357 :   return submsg;
     144     3359357 : }
     145             : 
     146             : /* fd_pb_tlv_skip skips the value of a TLV.  Returns the value that was
     147             :    skipped on success.  On failure (corrupt Protobuf), returns NULL. */
     148             : 
     149             : static inline uchar const *
     150             : fd_pb_tlv_skip( fd_pb_inbuf_t *     buf,
     151           0 :                 fd_pb_tlv_t const * tlv ) {
     152           0 :   uchar const * ret = buf->cur;
     153           0 :   if( tlv->wire_type==FD_PB_WIRE_TYPE_LEN ) {
     154           0 :     if( FD_UNLIKELY( tlv->len > fd_pb_inbuf_sz( buf ) ) ) return NULL;
     155           0 :     buf->cur += tlv->len;
     156           0 :   }
     157           0 :   return ret;
     158           0 : }
     159             : 
     160             : FD_PROTOTYPES_END
     161             : 
     162             : #endif /* HEADER_fd_src_ballet_pb_fd_pb_tokenize_h */

Generated by: LCOV version 1.14