LCOV - code coverage report
Current view: top level - flamenco/types - fd_bincode.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 123 355 34.6 %
Date: 2025-10-27 04:40:00 Functions: 23 16611 0.1 %

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

Generated by: LCOV version 1.14