LCOV - code coverage report
Current view: top level - flamenco/types - fd_bincode.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 191 365 52.3 %
Date: 2025-07-01 05:00:49 Functions: 31 9898 0.3 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_encoders_fd_bincode_h
       2             : #define HEADER_fd_src_util_encoders_fd_bincode_h
       3             : 
       4             : #include "../../util/fd_util.h"
       5             : #include "../../util/valloc/fd_valloc.h"
       6             : 
       7             : typedef void
       8             : (* fd_types_walk_fn_t)( void *       self,
       9             :                         void const * arg,
      10             :                         char const * name,
      11             :                         int          type,
      12             :                         char const * type_name,
      13             :                         uint         level );
      14             : 
      15             : typedef void
      16             : (* fd_types_walk_fn_t)( void *       self,
      17             :                         void const * arg,
      18             :                         char const * name,
      19             :                         int          type,
      20             :                         char const * type_name,
      21             :                         uint         level );
      22             : 
      23             : /* Context argument used for encoding */
      24             : struct fd_bincode_encode_ctx {
      25             :   /* Current position in data buffer */
      26             :   void * data;
      27             :   /* End of buffer */
      28             :   void * dataend;
      29             : };
      30             : typedef struct fd_bincode_encode_ctx fd_bincode_encode_ctx_t;
      31             : 
      32             : /* Context argument used for decoding */
      33             : struct fd_bincode_decode_ctx {
      34             :   /* Current position in data buffer */
      35             :   void const * data;
      36             :   /* End of buffer */
      37             :   void const * dataend;
      38             : };
      39             : typedef struct fd_bincode_decode_ctx fd_bincode_decode_ctx_t;
      40             : 
      41        8052 : #define FD_BINCODE_SUCCESS         (    0)
      42           0 : #define FD_BINCODE_ERR_UNDERFLOW   (-1001) /* Attempted to read past end of buffer */
      43           3 : #define FD_BINCODE_ERR_OVERFLOW    (-1002) /* Attempted to write past end of buffer */
      44           6 : #define FD_BINCODE_ERR_ENCODING    (-1003) /* Invalid encoding */
      45             : 
      46             : #define FD_BINCODE_PRIMITIVE_STUBS( name, type ) \
      47             :   static inline int \
      48             :   fd_bincode_##name##_decode( type *                    self, \
      49         330 :                               fd_bincode_decode_ctx_t * ctx ) { \
      50         330 :     uchar const * ptr = (uchar const *) ctx->data; \
      51         330 :     if ( FD_UNLIKELY((void const *)(ptr + sizeof(type)) > ctx->dataend ) ) \
      52         330 :       return FD_BINCODE_ERR_UNDERFLOW; \
      53         330 :     memcpy( self, ptr, sizeof(type) );  /* unaligned */ \
      54         330 :     ctx->data = ptr + sizeof(type); \
      55         330 :     return FD_BINCODE_SUCCESS; \
      56         330 :   } \
      57             :   static inline int \
      58         777 :   fd_bincode_##name##_decode_footprint( fd_bincode_decode_ctx_t * ctx ) { \
      59         777 :     uchar const * ptr = (uchar const *) ctx->data; \
      60         777 :     if ( FD_UNLIKELY((void const *)(ptr + sizeof(type)) > ctx->dataend ) ) \
      61         777 :       return FD_BINCODE_ERR_UNDERFLOW; \
      62         777 :     ctx->data = ptr + sizeof(type); \
      63         777 :     return FD_BINCODE_SUCCESS; \
      64         777 :   } \
      65             :   static inline void \
      66             :   fd_bincode_##name##_decode_unsafe( type *                    self, \
      67        3894 :                                      fd_bincode_decode_ctx_t * ctx ) { \
      68        3894 :     uchar const * ptr = (uchar const *) ctx->data; \
      69        3894 :     memcpy( self, ptr, sizeof(type) );  /* unaligned */ \
      70        3894 :     ctx->data = ptr + sizeof(type); \
      71        3894 :   } \
      72             :   static inline int \
      73             :   fd_bincode_##name##_encode( type                      self, \
      74        3444 :                               fd_bincode_encode_ctx_t * ctx ) { \
      75        3444 :     uchar * ptr = (uchar *)ctx->data; \
      76        3444 :     if ( FD_UNLIKELY((void *)(ptr + sizeof(type)) > ctx->dataend ) ) \
      77        3444 :       return FD_BINCODE_ERR_OVERFLOW; \
      78        3444 :     memcpy( ptr, &self, sizeof(type) );  /* unaligned */ \
      79        3441 :     ctx->data = ptr + sizeof(type); \
      80        3441 :     return FD_BINCODE_SUCCESS; \
      81        3444 :   }
      82             : 
      83             : FD_BINCODE_PRIMITIVE_STUBS( uint8,   uchar   )
      84             : FD_BINCODE_PRIMITIVE_STUBS( uint16,  ushort  )
      85             : FD_BINCODE_PRIMITIVE_STUBS( uint32,  uint    )
      86             : FD_BINCODE_PRIMITIVE_STUBS( uint64,  ulong   )
      87             : FD_BINCODE_PRIMITIVE_STUBS( int64,   long   )
      88             : #if FD_HAS_INT128
      89             : FD_BINCODE_PRIMITIVE_STUBS( uint128, uint128 )
      90             : #endif
      91             : FD_BINCODE_PRIMITIVE_STUBS( double,  double  )
      92             : 
      93             : static inline int
      94             : fd_bincode_bool_decode( uchar *                   self,
      95          51 :                         fd_bincode_decode_ctx_t * ctx ) {
      96             : 
      97          51 :   uchar const * ptr = (uchar const *)ctx->data;
      98          51 :   if( FD_UNLIKELY( ptr+1 > (uchar const *)ctx->dataend ) )
      99           0 :     return FD_BINCODE_ERR_UNDERFLOW;
     100             : 
     101          51 :   if( FD_UNLIKELY( *ptr & (~1U) ) )
     102           3 :     return FD_BINCODE_ERR_ENCODING;
     103             : 
     104          48 :   *self = *ptr;
     105          48 :   ctx->data = ptr + 1;
     106             : 
     107          48 :   return FD_BINCODE_SUCCESS;
     108          51 : }
     109             : 
     110             : static inline int
     111          36 : fd_bincode_bool_decode_footprint( fd_bincode_decode_ctx_t * ctx ) {
     112             : 
     113          36 :   uchar const * ptr = (uchar const *)ctx->data;
     114          36 :   if( FD_UNLIKELY( ptr+1 > (uchar const *)ctx->dataend ) )
     115           0 :     return FD_BINCODE_ERR_UNDERFLOW;
     116             : 
     117          36 :   if( FD_UNLIKELY( *ptr & (~1U) ) )
     118           3 :     return FD_BINCODE_ERR_ENCODING;
     119             : 
     120          33 :   ctx->data = ptr + 1;
     121             : 
     122          33 :   return FD_BINCODE_SUCCESS;
     123          36 : }
     124             : 
     125             : static inline void
     126             : fd_bincode_bool_decode_unsafe( uchar *                   self,
     127          81 :                                fd_bincode_decode_ctx_t * ctx ) {
     128          81 :   fd_bincode_uint8_decode_unsafe( self, ctx );
     129          81 : }
     130             : 
     131             : static inline int
     132             : fd_bincode_bool_encode( uchar                     self,
     133         258 :                         fd_bincode_encode_ctx_t * ctx ) {
     134             : 
     135         258 :   uchar * ptr = (uchar *)ctx->data;
     136         258 :   if ( FD_UNLIKELY( (void *)(ptr + 1) > ctx->dataend ) )
     137           0 :     return FD_BINCODE_ERR_OVERFLOW;
     138             : 
     139         258 :   *ptr = !!self;
     140         258 :   ctx->data = ptr + 1;
     141             : 
     142         258 :   return FD_BINCODE_SUCCESS;
     143         258 : }
     144             : 
     145             : static inline int
     146             : fd_bincode_bytes_decode( uchar *                   self,
     147             :                          ulong                     len,
     148           0 :                          fd_bincode_decode_ctx_t * ctx ) {
     149           0 :   uchar * ptr = (uchar *) ctx->data;
     150           0 :   if ( FD_UNLIKELY((ulong)( (uchar *) ctx->dataend - ptr) < len ) ) // Get wrap-around case right
     151           0 :     return FD_BINCODE_ERR_UNDERFLOW;
     152           0 : 
     153           0 :   fd_memcpy(self, ptr, len);
     154           0 :   ctx->data = ptr + len;
     155           0 : 
     156           0 :   return FD_BINCODE_SUCCESS;
     157           0 : }
     158             : 
     159             : static inline int
     160             : fd_bincode_bytes_decode_footprint( ulong                     len,
     161         237 :                                    fd_bincode_decode_ctx_t * ctx ) {
     162         237 :   uchar * ptr = (uchar *) ctx->data;
     163         237 :   if ( FD_UNLIKELY((ulong)( (uchar *) ctx->dataend - ptr) < len ) ) { // Get wrap-around case right
     164           0 :     return FD_BINCODE_ERR_UNDERFLOW;
     165           0 :   }
     166             : 
     167         237 :   ctx->data = ptr + len;
     168             : 
     169         237 :   return FD_BINCODE_SUCCESS;
     170         237 : }
     171             : 
     172             : static inline void
     173             : fd_bincode_bytes_decode_unsafe( uchar *                   self,
     174             :                                 ulong                     len,
     175         657 :                                 fd_bincode_decode_ctx_t * ctx ) {
     176         657 :   uchar * ptr = (uchar *) ctx->data;
     177         657 :   fd_memcpy(self, ptr, len);
     178         657 :   ctx->data = ptr + len;
     179         657 : }
     180             : 
     181             : static inline int
     182             : fd_bincode_bytes_encode( uchar const *             self,
     183             :                          ulong                     len,
     184        1032 :                          fd_bincode_encode_ctx_t * ctx ) {
     185        1032 :   fd_msan_check( self, len );
     186             : 
     187        1032 :   uchar * ptr = (uchar *)ctx->data;
     188        1032 :   if( FD_UNLIKELY( (void *)( ptr+len ) > ctx->dataend ) )
     189           0 :     return FD_BINCODE_ERR_OVERFLOW;
     190             : 
     191        1032 :   fd_memcpy( ptr, self, len );
     192        1032 :   ctx->data = ptr + len;
     193             : 
     194        1032 :   return FD_BINCODE_SUCCESS;
     195        1032 : }
     196             : 
     197             : /* Alternate versions of fd_cu16_dec to make the function signature more consistent with the
     198             :    other fd_bincode_decode functions.  */
     199             : static inline int
     200             : fd_bincode_compact_u16_decode( ushort *                  self,
     201          57 :                                fd_bincode_decode_ctx_t * ctx ) {
     202          57 :   const uchar * ptr = (const uchar*) ctx->data;
     203          57 :   if( FD_UNLIKELY( ptr==NULL ) ) {
     204           0 :     return FD_BINCODE_ERR_UNDERFLOW;
     205           0 :   }
     206             : 
     207          57 :   if( FD_LIKELY( (void *) (ptr + 1) <= ctx->dataend && !(0x80U & ptr[0]) ) ) {
     208          51 :     *self = (ushort)ptr[0];
     209          51 :     ctx->data = ptr + 1;
     210          51 :     return FD_BINCODE_SUCCESS;
     211          51 :   }
     212             : 
     213           6 :   if( FD_LIKELY( (void *) (ptr + 2) <= ctx->dataend && !(0x80U & ptr[1]) ) ) {
     214           6 :     if( FD_UNLIKELY( !ptr[1] ) ) /* Detect non-minimal encoding */
     215           0 :       return FD_BINCODE_ERR_ENCODING;
     216           6 :     *self = (ushort)((ulong)(ptr[0]&0x7FUL) + (((ulong)ptr[1])<<7));
     217           6 :     ctx->data = ptr + 2;
     218           6 :     return FD_BINCODE_SUCCESS;
     219           6 :   }
     220             : 
     221           0 :   if( FD_LIKELY( (void *) (ptr + 3) <= ctx->dataend && !(0xFCU & ptr[2]) ) ) {
     222           0 :     if( FD_UNLIKELY( !ptr[2] ) ) /* Detect non-minimal encoding */
     223           0 :       return FD_BINCODE_ERR_ENCODING;
     224           0 :     *self = (ushort)((ulong)(ptr[0]&0x7FUL) + (((ulong)(ptr[1]&0x7FUL))<<7) + (((ulong)ptr[2])<<14));
     225           0 :     ctx->data = ptr + 3;
     226           0 :     return FD_BINCODE_SUCCESS;
     227           0 :   }
     228             : 
     229           0 :   return FD_BINCODE_ERR_UNDERFLOW;
     230           0 : }
     231             : 
     232             : static inline void
     233             : fd_bincode_compact_u16_decode_unsafe( ushort *                  self,
     234          57 :                                       fd_bincode_decode_ctx_t * ctx ) {
     235          57 :   const uchar * ptr = (const uchar*) ctx->data;
     236             : 
     237          57 :   if( !(0x80U & ptr[0]) ) {
     238          51 :     *self = (ushort)ptr[0];
     239          51 :     ctx->data = ptr + 1;
     240          51 :     return;
     241          51 :   }
     242             : 
     243           6 :   if( !(0x80U & ptr[1]) ) {
     244           6 :     *self = (ushort)((ulong)(ptr[0]&0x7FUL) + (((ulong)ptr[1])<<7));
     245           6 :     ctx->data = ptr + 2;
     246           6 :     return;
     247           6 :   }
     248             : 
     249           0 :   *self = (ushort)((ulong)(ptr[0]&0x7FUL) + (((ulong)(ptr[1]&0x7FUL))<<7) + (((ulong)ptr[2])<<14));
     250           0 :   ctx->data = ptr + 3;
     251           0 : }
     252             : 
     253             : static inline int
     254             : fd_bincode_compact_u16_encode( ushort const *            self,
     255          12 :                                fd_bincode_encode_ctx_t * ctx ) {
     256          12 :   uchar * ptr = (uchar*) ctx->data;
     257          12 :   ulong val = *self;
     258             : 
     259          12 :   if ( val < 0x80UL ) {
     260          12 :     if ( FD_UNLIKELY((void *) (ptr + 1) > ctx->dataend ) )
     261           0 :       return FD_BINCODE_ERR_OVERFLOW;
     262          12 :     *ptr = (uchar)val;
     263          12 :     ctx->data = ptr + 1;
     264          12 :     return FD_BINCODE_SUCCESS;
     265          12 :   }
     266             : 
     267           0 :   else if ( val < 0x4000UL ) {
     268           0 :     if ( FD_UNLIKELY((void *) (ptr + 2) > ctx->dataend ) )
     269           0 :       return FD_BINCODE_ERR_OVERFLOW;
     270           0 :     ptr[0] = (uchar)((val&0x7FUL)|0x80UL);
     271           0 :     ptr[1] = (uchar)(val>>7);
     272           0 :     ctx->data = ptr + 2;
     273           0 :     return FD_BINCODE_SUCCESS;
     274           0 :   }
     275             : 
     276           0 :   else {
     277           0 :     if ( FD_UNLIKELY((void *) (ptr + 3) > ctx->dataend ) )
     278           0 :       return FD_BINCODE_ERR_OVERFLOW;
     279           0 :     ptr[0] = (uchar)((val&0x7FUL)|0x80UL);
     280           0 :     ptr[1] = (uchar)(((val>>7)&0x7FUL)|0x80UL);
     281           0 :     ptr[2] = (uchar)(val>>14);
     282           0 :     ctx->data = ptr + 3;
     283           0 :     return FD_BINCODE_SUCCESS;
     284           0 :   }
     285          12 : }
     286             : 
     287             : static inline ulong
     288           0 : fd_bincode_compact_u16_size( ushort const * self ) {
     289           0 :   ulong val = *self;
     290             : 
     291           0 :   if ( val < 0x80UL ) {
     292           0 :     return 1;
     293           0 :   }
     294           0 :   else if ( val < 0x4000UL ) {
     295           0 :     return 2;
     296           0 :   }
     297           0 :   else {
     298           0 :     return 3;
     299           0 :   }
     300           0 : }
     301             : 
     302             : /* Decodes an integer encoded using the serde_varint algorithm:
     303             :    https://github.com/solana-labs/solana/blob/master/sdk/program/src/serde_varint.rs
     304             : 
     305             :    A variable number of bytes could have been used to encode the integer.
     306             :    The most significant bit of each byte indicates if more bytes have been used, so we keep consuming until
     307             :    we reach a byte where the most significant bit is 0.
     308             : */
     309             : static inline int
     310             : fd_bincode_varint_decode( ulong *                   self,
     311           0 :                           fd_bincode_decode_ctx_t * ctx ) {
     312           0 :   ulong out   = 0UL;
     313           0 :   uint  shift = 0U;
     314           0 : 
     315           0 :   while( FD_LIKELY( shift < 64U ) ) {
     316           0 : 
     317           0 :     if( FD_UNLIKELY( ctx->data >= ctx->dataend ) )
     318           0 :       return FD_BINCODE_ERR_UNDERFLOW;
     319           0 : 
     320           0 :     uint byte = *(uchar const *)ctx->data;
     321           0 :     ctx->data = (uchar const *)ctx->data + 1;
     322           0 :     out |= (byte & 0x7FUL) << shift;
     323           0 : 
     324           0 :     if( (byte & 0x80U) == 0U ) {
     325           0 :       if( (out>>shift) != byte )
     326           0 :         return FD_BINCODE_ERR_ENCODING;
     327           0 :       if( byte==0U && (shift!=0U || out!=0UL) )
     328           0 :         return FD_BINCODE_ERR_ENCODING;
     329           0 :       *self = out;
     330           0 :       return FD_BINCODE_SUCCESS;
     331           0 :     }
     332           0 : 
     333           0 :     shift += 7U;
     334           0 : 
     335           0 :   }
     336           0 : 
     337           0 :   return FD_BINCODE_ERR_ENCODING;
     338           0 : }
     339             : 
     340             : static inline int
     341           3 : fd_bincode_varint_decode_footprint( fd_bincode_decode_ctx_t * ctx ) {
     342           3 :   ulong out   = 0UL;
     343           3 :   uint  shift = 0U;
     344             : 
     345          18 :   while( FD_LIKELY( shift < 64U ) ) {
     346             : 
     347          18 :     if( FD_UNLIKELY( ctx->data >= ctx->dataend ) )
     348           0 :       return FD_BINCODE_ERR_UNDERFLOW;
     349             : 
     350          18 :     uint byte = *(uchar const *)ctx->data;
     351          18 :     ctx->data = (uchar const *)ctx->data + 1;
     352          18 :     out |= (byte & 0x7FUL) << shift;
     353             : 
     354          18 :     if( (byte & 0x80U) == 0U ) {
     355           3 :       if( (out>>shift) != byte )
     356           0 :         return FD_BINCODE_ERR_ENCODING;
     357           3 :       if( byte==0U && (shift!=0U || out!=0UL) )
     358           0 :         return FD_BINCODE_ERR_ENCODING;
     359           3 :       return FD_BINCODE_SUCCESS;
     360           3 :     }
     361             : 
     362          15 :     shift += 7U;
     363             : 
     364          15 :   }
     365             : 
     366           0 :   return FD_BINCODE_ERR_ENCODING;
     367           3 : }
     368             : 
     369             : static inline void
     370             : fd_bincode_varint_decode_unsafe( ulong *                   self,
     371           3 :                                  fd_bincode_decode_ctx_t * ctx ) {
     372           3 :   ulong out   = 0UL;
     373           3 :   uint  shift = 0U;
     374             : 
     375          18 :   for(;;) {
     376          18 :     uint byte = *(uchar const *)ctx->data;
     377          18 :     ctx->data = (uchar const *)ctx->data + 1;
     378          18 :     out |= (byte & 0x7FUL) << shift;
     379             : 
     380          18 :     if( (byte & 0x80U) == 0U ) {
     381           3 :       *self = out;
     382           3 :       return;
     383           3 :     }
     384             : 
     385          15 :     shift += 7U;
     386          15 :   }
     387           3 : }
     388             : 
     389             : static inline int
     390             : fd_bincode_varint_encode( ulong                     val,
     391           0 :                           fd_bincode_encode_ctx_t * ctx ) {
     392           0 :   uchar * ptr = (uchar *) ctx->data;
     393           0 :   while (1) {
     394           0 :     if ( FD_UNLIKELY((void *) (ptr + 1) > ctx->dataend ) )
     395           0 :       return FD_BINCODE_ERR_OVERFLOW;
     396           0 :     if ( val < 0x80UL ) {
     397           0 :       *(ptr++) = (uchar)val;
     398           0 :       ctx->data = ptr;
     399           0 :       return FD_BINCODE_SUCCESS;
     400           0 :     }
     401           0 :     *(ptr++) = (uchar)((val&0x7FUL)|0x80UL);
     402           0 :     val >>= 7;
     403           0 :   }
     404           0 : }
     405             : 
     406             : static inline ulong
     407           0 : fd_bincode_varint_size( ulong val ) {
     408           0 :   ulong sz = 0;
     409           0 :   while (1) {
     410           0 :     if ( val < 0x80UL ) {
     411           0 :       return sz+1;
     412           0 :     }
     413           0 :     sz++;
     414           0 :     val >>= 7;
     415           0 :   }
     416           0 : }
     417             : 
     418             : enum {
     419             :   /* All meta tags must fit in 6 bits */
     420             : 
     421             :   /* Primitive types with an implicit encoding length */
     422             :   FD_ARCHIVE_META_CHAR = 0x1,
     423             :   FD_ARCHIVE_META_STRING = 0x2,
     424             :   FD_ARCHIVE_META_CHAR32 = 0x3,
     425             :   FD_ARCHIVE_META_DOUBLE = 0x4,
     426             :   FD_ARCHIVE_META_LONG = 0x5,
     427             :   FD_ARCHIVE_META_UINT = 0x6,
     428             :   FD_ARCHIVE_META_UINT128 = 0x7,
     429             :   FD_ARCHIVE_META_BOOL = 0x8,
     430             :   FD_ARCHIVE_META_UCHAR = 0x9,
     431             :   FD_ARCHIVE_META_UCHAR32 = 0xa,
     432             :   FD_ARCHIVE_META_UCHAR128 = 0xb,
     433             :   FD_ARCHIVE_META_UCHAR2048 = 0xc,
     434             :   FD_ARCHIVE_META_ULONG = 0xd,
     435             :   FD_ARCHIVE_META_USHORT = 0xe,
     436             : 
     437             :   /* Meta types which have an encoding length after the short tag */
     438             :   FD_ARCHIVE_META_STRUCT = 0x21,
     439             :   FD_ARCHIVE_META_VECTOR = 0x22,
     440             :   FD_ARCHIVE_META_DEQUE = 0x23,
     441             :   FD_ARCHIVE_META_MAP = 0x24,
     442             :   FD_ARCHIVE_META_TREAP = 0x25,
     443             :   FD_ARCHIVE_META_OPTION = 0x26,
     444             :   FD_ARCHIVE_META_ARRAY = 0x27,
     445             :   FD_ARCHIVE_META_STATIC_VECTOR = 0x28,
     446             : };
     447             : 
     448             : #define FD_ARCHIVE_META_SENTINAL (ushort)0 /* End of structure */
     449             : 
     450           0 : static inline int fd_archive_encode_setup_length( fd_bincode_encode_ctx_t * ctx, void ** offset_out ) {
     451           0 :   uchar * ptr = (uchar *)ctx->data;
     452           0 :   if ( FD_UNLIKELY((void *)(ptr + sizeof(uint)) > ctx->dataend ) )
     453           0 :     return FD_BINCODE_ERR_OVERFLOW;
     454           0 :   /* Skip over length for now but make space for it */
     455           0 :   *offset_out = ptr;
     456           0 :   ctx->data = ptr + sizeof(uint);
     457           0 :   return FD_BINCODE_SUCCESS;
     458           0 : }
     459             : 
     460           0 : static inline int fd_archive_encode_set_length( fd_bincode_encode_ctx_t * ctx, void * offset ) {
     461           0 :   *(uint *)offset = (uint)((uchar *)ctx->data - ((uchar *)offset + sizeof(uint)));
     462           0 :   return FD_BINCODE_SUCCESS;
     463           0 : }
     464             : 
     465           0 : static inline int fd_archive_decode_setup_length( fd_bincode_decode_ctx_t * ctx, void ** offset_out ) {
     466           0 :   uchar * ptr = (uchar *)ctx->data;
     467           0 :   if ( FD_UNLIKELY((void *)(ptr + sizeof(uint)) > ctx->dataend ) )
     468           0 :     return FD_BINCODE_ERR_UNDERFLOW;
     469           0 :   /* Skip over length for now and verify it later */
     470           0 :   *offset_out = ptr;
     471           0 :   ctx->data = ptr + sizeof(uint);
     472           0 :   return FD_BINCODE_SUCCESS;
     473           0 : }
     474             : 
     475           0 : static inline int fd_archive_decode_check_length( fd_bincode_decode_ctx_t * ctx, void * offset ) {
     476           0 :   if( *(uint *)offset != (uint)((uchar *)ctx->data - ((uchar *)offset + sizeof(uint))) )
     477           0 :     return FD_BINCODE_ERR_ENCODING;
     478           0 :   return FD_BINCODE_SUCCESS;
     479           0 : }
     480             : 
     481             : /* Convenience API for deserializing with common allocators */
     482             : 
     483             : /* fd_bincode_decode_spad decodes a bincode type.  The result is
     484             :    allocated into a spad on success.  On failure, no spad allocations
     485             :    are made.
     486             : 
     487             :    fd_bincode_decode1_spad optionally outputs the number of bytes read
     488             :    to *psz. */
     489             : 
     490             : #define fd_bincode_decode1_spad( type, spad, buf, buf_sz, perr, psz )  \
     491           6 :   __extension__({                                                      \
     492           6 :     fd_spad_t *  const spad_   = (spad);                               \
     493           6 :     void const * const buf_    = (buf);                                \
     494           6 :     ulong        const buf_sz_ = (buf_sz);                             \
     495           6 :     int *              perr_   = (perr);                               \
     496           6 :     ulong *            psz_    = (psz);                                \
     497           6 :     fd_bincode_decode_ctx_t ctx = {0};                                 \
     498           6 :     if( perr_ ) *perr_ = -1;                                           \
     499           6 :     ctx.data    = (void const *)( buf_ );                              \
     500           6 :     ctx.dataend = (void const *)( (ulong)ctx.data + buf_sz_ );         \
     501           6 :     ulong total_sz = 0UL;                                              \
     502           6 :     int err = fd_##type##_decode_footprint( &ctx, &total_sz );         \
     503           6 :     fd_##type##_t * out = NULL;                                        \
     504           6 :     if( FD_LIKELY( err==FD_BINCODE_SUCCESS ) ) {                       \
     505           3 :       ulong align = fd_##type##_align();                               \
     506           3 :       void * mem = fd_spad_alloc( spad_, align, total_sz );            \
     507           3 :       if( FD_UNLIKELY( !mem ) ) {                                      \
     508           0 :         FD_LOG_ERR(( "fd_bincode_" #type "_decode failed: out of memory (decode requires %lu+%lu bytes, but only %lu bytes free in spad)", align-1UL, total_sz, fd_spad_mem_free( spad_ ) )); \
     509           0 :       }                                                                \
     510           3 :       out = fd_##type##_decode( mem, &ctx );                           \
     511           3 :       if( psz_ ) *psz_ = (ulong)ctx.data - (ulong)buf_;                \
     512           3 :     }                                                                  \
     513           6 :     if( perr_ ) *perr_ = err;                                          \
     514           6 :     out;                                                               \
     515           6 :   })
     516             : 
     517             : #define fd_bincode_decode1_spad_global( type, spad, buf, buf_sz, perr, psz )  \
     518           9 :   __extension__({                                                             \
     519           9 :     fd_spad_t *  const spad_   = (spad);                                      \
     520           9 :     void const * const buf_    = (buf);                                       \
     521           9 :     ulong        const buf_sz_ = (buf_sz);                                    \
     522           9 :     int *              perr_   = (perr);                                      \
     523           9 :     ulong *            psz_    = (psz);                                       \
     524           9 :     fd_bincode_decode_ctx_t ctx = {0};                                        \
     525           9 :     if( perr_ ) *perr_ = -1;                                                  \
     526           9 :     ctx.data    = (void const *)( buf_ );                                     \
     527           9 :     ctx.dataend = (void const *)( (ulong)ctx.data + buf_sz_ );                \
     528           9 :     ulong total_sz = 0UL;                                                     \
     529           9 :     int err = fd_##type##_decode_footprint( &ctx, &total_sz );                \
     530           9 :     fd_##type##_global_t * out = NULL;                                        \
     531           9 :     if( FD_LIKELY( err==FD_BINCODE_SUCCESS ) ) {                              \
     532           6 :       ulong align = fd_##type##_align();                                      \
     533           6 :       void * mem = fd_spad_alloc( spad_, align, total_sz );                   \
     534           6 :       if( FD_UNLIKELY( !mem ) ) {                                             \
     535           0 :         FD_LOG_ERR(( "fd_bincode_" #type "_decode failed: out of memory (decode requires %lu+%lu bytes, but only %lu bytes free in spad)", align-1UL, total_sz, fd_spad_mem_free( spad_ ) )); \
     536           0 :       }                                                                       \
     537           6 :       out = fd_##type##_decode_global( mem, &ctx );                           \
     538           6 :       if( psz_ ) *psz_ = (ulong)ctx.data - (ulong)buf_;                       \
     539           6 :     }                                                                         \
     540           9 :     if( perr_ ) *perr_ = err;                                                 \
     541           9 :     out;                                                                      \
     542           9 :   })
     543             : 
     544             : #define fd_bincode_decode_spad( type, spad, buf, buf_sz, perr ) \
     545           6 :   fd_bincode_decode1_spad( type, spad, buf, buf_sz, perr, NULL )
     546             : 
     547             : #define fd_bincode_decode_spad_global( type, spad, buf, buf_sz, perr ) \
     548           9 :   fd_bincode_decode1_spad_global( type, spad, buf, buf_sz, perr, NULL )
     549             : 
     550             : /* fd_bincode_decode_scratch decodes a bincode type.  The result is
     551             :    allocated into the thread's scratch region on success.  On failure,
     552             :    no allocations are made. */
     553             : 
     554             : #define fd_bincode_decode1_scratch( type, buf, buf_sz, perr, psz )     \
     555           0 :   __extension__({                                                      \
     556           0 :     void const * const buf_    = (buf);                                \
     557           0 :     ulong        const buf_sz_ = (buf_sz);                             \
     558           0 :     int *              perr_   = (perr);                               \
     559           0 :     ulong *            psz_    = (psz);                                \
     560           0 :     fd_bincode_decode_ctx_t ctx = {0};                                 \
     561           0 :     if( perr_ ) *perr_ = -1;                                           \
     562           0 :     ctx.data    = (void const *)( buf_ );                              \
     563           0 :     ctx.dataend = (void const *)( (ulong)ctx.data + buf_sz_ );         \
     564           0 :     ulong total_sz = 0UL;                                              \
     565           0 :     int err = fd_##type##_decode_footprint( &ctx, &total_sz );         \
     566           0 :     fd_##type##_t * out = NULL;                                        \
     567           0 :     if( FD_LIKELY( err==FD_BINCODE_SUCCESS ) ) {                       \
     568           0 :       ulong align = fd_##type##_align();                               \
     569           0 :       if( FD_UNLIKELY( !fd_scratch_alloc_is_safe( align, total_sz ) ) ) { \
     570           0 :         FD_LOG_ERR(( "fd_bincode_" #type "_decode failed: out of memory (decode requires %lu+%lu bytes, but only %lu bytes free in scratch region)", align-1UL, total_sz, fd_scratch_free() )); \
     571           0 :       }                                                                \
     572           0 :       void * mem = fd_scratch_alloc( align, total_sz );                \
     573           0 :       out = fd_##type##_decode( mem, &ctx );                           \
     574           0 :       if( psz_ ) *psz_ = (ulong)ctx.data - (ulong)buf_;                \
     575           0 :     }                                                                  \
     576           0 :     if( perr_ ) *perr_ = err;                                          \
     577           0 :     out;                                                               \
     578           0 :   })
     579             : 
     580             : #define fd_bincode_decode_scratch( type, buf, buf_sz, perr ) \
     581           0 :   fd_bincode_decode1_scratch( type, buf, buf_sz, perr, NULL )
     582             : 
     583             : #endif /* HEADER_fd_src_util_encoders_fd_bincode_h */

Generated by: LCOV version 1.14