Line data Source code
1 : #ifndef HEADER_fd_src_waltz_h2_fd_hpack_private_h 2 : #define HEADER_fd_src_waltz_h2_fd_hpack_private_h 3 : 4 : #include "fd_hpack.h" 5 : 6 : #if FD_HAS_X86 7 : #include <immintrin.h> 8 : #endif 9 : 10 : /* Simple HPACK static table. 11 : FIXME could be made faster/smaller */ 12 : 13 : struct fd_hpack_static_entry { 14 : char const * entry; 15 : uchar name_len; 16 : uchar value_len; 17 : }; 18 : 19 : typedef struct fd_hpack_static_entry fd_hpack_static_entry_t; 20 : 21 : FD_PROTOTYPES_BEGIN 22 : 23 : extern fd_hpack_static_entry_t const 24 : fd_hpack_static_table[ 62 ]; 25 : 26 : /* fd_hpack_rd_varint reads a varint with up to 8 bytes encoded length 27 : (not including prefix). addend is (2^n)-1 where n is the varint 28 : prefix bit count. prefix is the actual value of the varint prefix. 29 : Returns a value in [0,2^56) on success. Returns ULONG_MAX on decode 30 : failure. */ 31 : 32 : static inline ulong 33 : fd_hpack_rd_varint( fd_hpack_rd_t * rd, 34 : uint prefix, 35 480 : uint addend ) { 36 480 : prefix &= addend; 37 : /* FIXME does not detect overflow */ 38 : 39 : /* Length is 0 */ 40 480 : if( prefix<addend ) return prefix; 41 : 42 : /* Read encoded word */ 43 114 : ulong enc = 0UL; 44 114 : if( FD_LIKELY( rd->src+8 <= rd->src_end ) ) { 45 : /* happy path: speculatively read oob */ 46 18 : enc = fd_ulong_load_8( rd->src ); 47 96 : } else { 48 : /* slow path: carefully memcpy, handle potentially corrupt src_end */ 49 96 : ulong sz = fd_ulong_min( (ulong)rd->src_end - (ulong)rd->src, 8UL ); 50 96 : if( FD_UNLIKELY( !sz ) ) return ULONG_MAX; /* eof */ 51 84 : fd_memcpy( &enc, rd->src, sz ); 52 84 : } 53 : 54 : /* sz_run is a bit pattern indicating: 55 : 56 : length 1 => least-significant one bit is at index 7 57 : length 2 => - " - 15 58 : ... 59 : length n => - " - (8*n)-1 */ 60 102 : ulong sz_run = ~( enc | 0x7f7f7f7f7f7f7f7fUL ); 61 102 : if( FD_UNLIKELY( sz_run==0 ) ) return ULONG_MAX; /* unterminated varint */ 62 102 : int sz_bits = fd_ulong_find_lsb( sz_run )+1; 63 102 : ulong sz = (ulong)sz_bits>>3; 64 : 65 : /* Mask off garbage bits */ 66 102 : enc &= fd_ulong_shift_left( 1UL, sz_bits )-1UL; 67 : 68 : /* Remove varint length bits */ 69 102 : #if FD_HAS_X86 && defined(__BMI2__) 70 102 : ulong result = _pext_u64( enc, 0x7f7f7f7f7f7f7f7fUL ); 71 : #else 72 : ulong result = 73 : ( ( enc&0x000000000000007fUL )>>0 ) | 74 : ( ( enc&0x0000000000007f00UL )>>1 ) | 75 : ( ( enc&0x00000000007f0000UL )>>2 ) | 76 : ( ( enc&0x000000007f000000UL )>>3 ) | 77 : ( ( enc&0x0000007f00000000UL )>>4 ) | 78 : ( ( enc&0x00007f0000000000UL )>>5 ) | 79 : ( ( enc&0x007f000000000000UL )>>6 ) | 80 : ( ( enc&0x7f00000000000000UL )>>7 ); 81 : #endif 82 : 83 102 : uchar const * src_end = rd->src+sz; 84 102 : if( FD_UNLIKELY( src_end>rd->src_end ) ) return ULONG_MAX; /* eof */ 85 93 : rd->src = src_end; 86 93 : return result+addend; 87 102 : } 88 : 89 : FD_PROTOTYPES_END 90 : 91 : #endif /* HEADER_fd_src_waltz_h2_fd_hpack_private_h */