LCOV - code coverage report
Current view: top level - ballet/txn - fd_compact_u16.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 38 38 100.0 %
Date: 2024-11-13 11:58:15 Functions: 6 36 16.7 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_txn_fd_compact_u16_h
       2             : #define HEADER_fd_src_ballet_txn_fd_compact_u16_h
       3             : 
       4             : /* This file declares some utility methods for decoding compact-u16, a variable
       5             :    length encoding format for unsigned 16 bit numbers that Solana transactions
       6             :    use in the wireline format.
       7             :    The format is documented at
       8             :    https://docs.solana.com/developing/programming-model/transactions#compact-u16-format
       9             :    but briefly:
      10             :      If the 16 bit number has (big endian bits) ponmlkji hgfedcba
      11             :      [  0x00,    0x80)   (implies [h..p] = 0) ->  0gfedcba                      (1 byte )
      12             :      [  0x80,  0x4000)   (implies [o..p] = 0) ->  1gfedcba 0nmlkjih             (2 bytes)
      13             :      [0x4000, 0x10000)                        ->  1gfedcba 1nmlkjih 000000po    (3 bytes)
      14             :    Numbers must be encoded with the minimal number of bytes possible.
      15             : 
      16             :    This encoding format is filled with sadness, some of which this API
      17             :    reflects.  To limit the sadness, this header is for internal use in fd_txn
      18             :    and not exported more widely. */
      19             : 
      20             : #include "../fd_ballet_base.h"
      21             : 
      22             : 
      23             : FD_PROTOTYPES_BEGIN
      24             : /* fd_cu16_dec_fixed: Reads a compact-u16 whose width is known.  High
      25             :    performance API that does no error checking, and as such, it's designed to
      26             :    be used with fd_cu16_dec_sz, which performs all necessary validation to
      27             :    ensure this is safe.  buf points to the first byte of the encoded value.
      28             :    sz in {1, 2, 3}. Reads exactly sz bytes. */
      29             : static inline ushort
      30             : fd_cu16_dec_fixed( uchar const * buf,
      31 10603858062 :                    ulong         sz ) {
      32             :   /* Branch-free hardware friendly format that is slower on a CPU. If you
      33             :      switch to this version, be sure to update the documentation to note that
      34             :      it reads more than sz bytes. */
      35             :   /*
      36             :      ulong w   = (ulong)*(uint *)buf;
      37             :      ulong b0  = (w & 0x00007FUL);
      38             :      ulong b1  = (w & 0x007F00UL)>>1UL;
      39             :      ulong b2  = (w & 0xFF0000UL)>>2UL;
      40             :      ulong m0  = (ulong)(((long)(1UL-sz))>>63); *//* Maps [0,1] to 0; [2,3] to 0xFF..FF */
      41             :   /* ulong m01 = (ulong)(((long)(2UL-sz))>>63); *//* Maps [0,2] to 0; [3,3] to 0xFF..FF */
      42             :   /* return (ushort)((b0) | (b1 & m0) | (b2 & m01)); */
      43             : 
      44             :   /* This version is actually substantially faster */
      45             : #if FD_TXN_HANDHOLDING
      46             :   FD_TEST( (1<=sz) & (sz<=3) )
      47             : #endif
      48 10603858062 :   if( FD_LIKELY( sz==1 ) )
      49  7357358433 :       return (ushort)buf[0];
      50  3246499629 :   if( FD_LIKELY( sz==2 ) )
      51  3208603425 :       return (ushort)((ulong)(buf[0]&0x7F) + (((ulong)buf[1])<<7));
      52    37896204 :   return (ushort)((ulong)(buf[0]&0x7F) + (((ulong)buf[1]&0x7F)<<7) + (((ulong)buf[2])<<14));
      53  3246499629 : }
      54             : 
      55             : /*fd_cu16_dec_sz: Returns the number of bytes in the compact-u16.  Also
      56             :   validates that it is a legally-encoded compact-u16 and that it is stored in
      57             :   no more than bytes_avail bytes.  buf points to the first byte of the encoded
      58             :   value.  Result will be in {0, 1, 2, 3}, where 0 indicates validation failed
      59             :   (not enough bytes avail, illegal encoding, or number is larger than a u16).*/
      60             : static inline ulong
      61             : fd_cu16_dec_sz( uchar const * buf,
      62 13825094706 :                 ulong         bytes_avail ) {
      63 13825094706 :   if( FD_LIKELY( bytes_avail>=1 && !(0x80UL & buf[0]) ) ) {
      64  7357358433 :     return 1UL;
      65  7357358433 :   }
      66  6467736273 :   if( FD_LIKELY( bytes_avail>=2 && !(0x80UL & buf[1]) ) ) {
      67  3233867946 :     if( FD_UNLIKELY( !buf[1] ) ) return 0UL; /* Detect non-minimal encoding */
      68  3208603425 :     return 2UL;
      69  3233867946 :   }
      70  3233868327 :   if( FD_LIKELY( bytes_avail>=3 && !(0xFCUL & buf[2]) ) ) {
      71    50528268 :     if( FD_UNLIKELY( !buf[2] ) ) return 0UL; /* Detect non-minimal encoding */
      72    37896204 :     return 3UL;
      73    50528268 :   }
      74  3183340059 :   return 0UL;
      75  3233868327 : }
      76             : 
      77             : /* fd_cu16_dec: Reads a compact-u16.  buf points to the first byte of the
      78             :    encoded value.  Validates that the compact-u16 is legally encoded, and
      79             :    returns 0 to indicate that validation failed.  If the compact-u16 is valid,
      80             :    the decoded value is stored in the location pointed to by result_out.  On
      81             :    success, returns the length of the encoded compact-u16. */
      82             : static inline ulong
      83             : fd_cu16_dec( uchar const * buf,
      84             :              ulong         bytes_avail,
      85 12935430915 :              ushort *      result_out ) {
      86 12935430915 :   ulong sz = fd_cu16_dec_sz( buf, bytes_avail );
      87 12935430915 :   if( sz ) *result_out = fd_cu16_dec_fixed( buf, sz );
      88 12935430915 :   return sz;
      89 12935430915 : }
      90             : 
      91             : static inline uint
      92      198147 : fd_cu16_enc( ushort val, uchar * out ) {
      93      198147 :   ulong v = (ulong)val;
      94      198147 :   ulong byte0 = (v    )&0x7FUL;
      95      198147 :   ulong byte1 = (v>> 7)&0x7FUL;
      96      198147 :   ulong byte2 = (v>>14);
      97      198147 :   int needs_byte1 = (v>0x007FUL);
      98      198147 :   int needs_byte2 = (v>0x3FFFUL);
      99      198147 :   fd_uchar_store_if( 1,           out + 0, (uchar)(byte0 | ((ulong)needs_byte1<<7)) );
     100      198147 :   fd_uchar_store_if( needs_byte1, out + 1, (uchar)(byte1 | ((ulong)needs_byte2<<7)) );
     101      198147 :   fd_uchar_store_if( needs_byte2, out + 2, (uchar)(byte2                          ) );
     102      198147 :   return (uint)(1+needs_byte1+needs_byte2);
     103      198147 : }
     104             : 
     105             : FD_PROTOTYPES_END
     106             : #endif /* HEADER_fd_src_ballet_txn_fd_compact_u16_h */

Generated by: LCOV version 1.14