Line data Source code
1 : #ifndef HEADER_fd_src_ballet_pb_fd_pb_wire_h 2 : #define HEADER_fd_src_ballet_pb_fd_pb_wire_h 3 : 4 : /* fd_pb_wire.h provides Protobuf wire format definitions and pure 5 : functions. */ 6 : 7 : #include "../../util/bits/fd_bits.h" 8 : #include "../../util/log/fd_log.h" 9 : 10 : /* Select a varint coding strategy */ 11 : 12 : #if defined(__BMI2__) && __LZCNT__ 13 : #if defined(__GNUC__) && !defined(__clang__) 14 : #include <x86gprintrin.h> 15 : #else 16 : #include <immintrin.h> 17 : #endif 18 : #define FD_PB_VARINT_CORE 1 /* x86 PDEP and LZCNT */ 19 : #else 20 : #define FD_PB_VARINT_CORE 0 /* portable */ 21 : #endif 22 : 23 : /* Message structure */ 24 : 25 6458561 : #define FD_PB_WIRE_TYPE_VARINT (0U) 26 10785663 : #define FD_PB_WIRE_TYPE_I64 (1U) 27 14266582 : #define FD_PB_WIRE_TYPE_LEN (2U) 28 132 : #define FD_PB_WIRE_TYPE_I32 (5U) 29 : 30 : static inline uint 31 : fd_pb_tag( uint wire_type, 32 6194383 : uint field_id ) { 33 6194383 : return ( field_id<<3 ) | wire_type; 34 6194383 : } 35 : 36 : static inline uint 37 10207950 : fd_pb_tag_wire_type( uint tag ) { 38 10207950 : return tag & 0x7U; 39 10207950 : } 40 : 41 : static inline uint 42 10112072 : fd_pb_tag_field_id( uint tag ) { 43 10112072 : return tag >> 3; 44 10112072 : } 45 : 46 : /* Max value sizes (template friendly) */ 47 : 48 : #define fd_pb_bool_max_sz (1U) 49 3546006 : #define fd_pb_varint32_sz_max (5U) 50 0 : #define fd_pb_varint64_sz_max (10U) 51 : #define fd_pb_int32_sz_max fd_pb_varint32_sz_max 52 : #define fd_pb_int64_sz_max fd_pb_varint64_sz_max 53 : #define fd_pb_uint32_sz_max fd_pb_varint32_sz_max 54 : #define fd_pb_uint64_sz_max fd_pb_varint64_sz_max 55 : #define fd_pb_sint32_sz_max fd_pb_varint32_sz_max 56 : #define fd_pb_sint64_sz_max fd_pb_varint64_sz_max 57 0 : #define fd_pb_fixed32_sz_max sizeof(uint) 58 0 : #define fd_pb_fixed64_sz_max sizeof(ulong) 59 : 60 : /* Value encoders */ 61 : 62 : static inline uchar * 63 : fd_pb_append_bool( uchar buf[ fd_pb_bool_max_sz ], 64 585175 : int value ) { 65 585175 : buf[0] = !!value; 66 585175 : return buf+1; 67 585175 : } 68 : 69 : #if FD_PB_VARINT_CORE==0 /* portable */ 70 : 71 : static inline uchar * 72 : fd_pb_append_varint32( uchar buf[ fd_pb_varint32_sz_max ], 73 : uint value ) { 74 : int msb = fd_uint_find_msb( value|1U )+1; 75 : buf[ 0 ] = (uchar)( ( msb> 7 ? 0x80 : 0 ) | ( (value>> 0) & 0x7f ) ); 76 : buf[ 1 ] = (uchar)( ( msb>14 ? 0x80 : 0 ) | ( (value>> 7) & 0x7f ) ); 77 : buf[ 2 ] = (uchar)( ( msb>21 ? 0x80 : 0 ) | ( (value>>14) & 0x7f ) ); 78 : buf[ 3 ] = (uchar)( ( msb>28 ? 0x80 : 0 ) | ( (value>>21) & 0x7f ) ); 79 : buf[ 4 ] = (uchar)( ( (value>>28) & 0x7f ) ); 80 : return buf+((msb+6)/7); 81 : } 82 : 83 : static inline uchar * 84 : fd_pb_append_varint32_sz5( uchar buf[ fd_pb_varint32_sz_max ], 85 : uint value ) { 86 : buf[ 0 ] = (uchar)( 0x80 | ( (value>> 0) & 0x7f ) ); 87 : buf[ 1 ] = (uchar)( 0x80 | ( (value>> 7) & 0x7f ) ); 88 : buf[ 2 ] = (uchar)( 0x80 | ( (value>>14) & 0x7f ) ); 89 : buf[ 3 ] = (uchar)( 0x80 | ( (value>>21) & 0x7f ) ); 90 : buf[ 4 ] = (uchar)( ( (value>>28) & 0x7f ) ); 91 : return buf+5; 92 : } 93 : 94 : static inline uchar * 95 : fd_pb_append_varint64( uchar buf[ fd_pb_varint64_sz_max ], 96 : ulong value ) { 97 : int msb = fd_ulong_find_msb( value|1U )+1; 98 : buf[ 0 ] = (uchar)( ( msb> 7 ? 0x80 : 0 ) | ( (value>> 0) & 0x7f ) ); 99 : buf[ 1 ] = (uchar)( ( msb>14 ? 0x80 : 0 ) | ( (value>> 7) & 0x7f ) ); 100 : buf[ 2 ] = (uchar)( ( msb>21 ? 0x80 : 0 ) | ( (value>>14) & 0x7f ) ); 101 : buf[ 3 ] = (uchar)( ( msb>28 ? 0x80 : 0 ) | ( (value>>21) & 0x7f ) ); 102 : buf[ 4 ] = (uchar)( ( msb>35 ? 0x80 : 0 ) | ( (value>>28) & 0x7f ) ); 103 : buf[ 5 ] = (uchar)( ( msb>42 ? 0x80 : 0 ) | ( (value>>35) & 0x7f ) ); 104 : buf[ 6 ] = (uchar)( ( msb>49 ? 0x80 : 0 ) | ( (value>>42) & 0x7f ) ); 105 : buf[ 7 ] = (uchar)( ( msb>56 ? 0x80 : 0 ) | ( (value>>49) & 0x7f ) ); 106 : buf[ 8 ] = (uchar)( ( msb>63 ? 0x80 : 0 ) | ( (value>>56) & 0x7f ) ); 107 : buf[ 9 ] = (uchar)( ( (value>>63) & 0x7f ) ); 108 : return buf+((msb+6)/7); 109 : } 110 : 111 : #elif FD_PB_VARINT_CORE==1 /* x86 PDEP and LZCNT */ 112 : 113 : static inline uchar * 114 : fd_pb_append_varint32( uchar buf[ fd_pb_varint32_sz_max ], 115 9329002 : uint value ) { 116 : /* Scatter bits */ 117 9329002 : ulong enc = _pdep_u64( value, 0x7f7f7f7f7f7f7f7fUL ); 118 : /* Count leading zeros */ 119 9329002 : uint lzc = (uint)_lzcnt_u64( enc|1 ); 120 : /* Generate continuation bits */ 121 9329002 : ulong cont = 0x80808080808080UL >> (lzc&0x38); 122 : /* Store result */ 123 9329002 : ulong res = enc|cont; 124 9329002 : FD_STORE( uint, buf, (uint)res ); 125 9329002 : buf[4] = (uchar)( res>>32 ); 126 9329002 : return buf+( 8-(lzc>>3) ); 127 9329002 : } 128 : 129 : static inline uchar * 130 : fd_pb_append_varint32_sz5( uchar buf[ fd_pb_varint32_sz_max ], 131 1183154 : uint value ) { 132 1183154 : FD_STORE( uint, buf, 0x80808080 | _pdep_u32( value, 0x7f7f7f7f ) ); 133 1183154 : buf[ 4 ] = (uchar)( (value>>28) & 0x7f ); 134 1183154 : return buf+5; 135 1183154 : } 136 : 137 : static inline uchar * 138 : fd_pb_append_varint64( uchar buf[ fd_pb_varint64_sz_max ], 139 1751423 : ulong value ) { 140 : /* Number of continuation bytes */ 141 1751423 : int len = fd_ulong_find_msb( value|1U )/7; 142 : /* Scatter bits */ 143 1751423 : ulong const scatter = 0x7f7f7f7f7f7f7f7fUL; 144 1751423 : ulong enc0 = _pdep_u64( value, scatter ); 145 1751423 : ulong enc1 = _pdep_u64( value>>56, scatter ); 146 : /* Generate continuation bits */ 147 1751423 : ulong const pattern = 0x8080808080808080UL; 148 1751423 : ulong cont0 = _bzhi_u64( pattern, (uint)fd_uint_min( (uint)( len <<3 ), 64 ) ); 149 1751423 : ulong cont1 = _bzhi_u64( pattern, ( (uint)len-8U )<<3 ); 150 : /* Store result */ 151 1751423 : FD_STORE( ulong, buf, enc0|cont0 ); 152 1751423 : FD_STORE( ushort, buf+8, (ushort)( enc1|cont1 ) ); 153 1751423 : return buf+len+1; 154 1751423 : } 155 : 156 : #endif /* varint cores */ 157 : 158 : static inline uchar * 159 : fd_pb_append_tag( uchar buf[ fd_pb_int32_sz_max ], 160 6191500 : ulong tag ) { 161 6191500 : return fd_pb_append_varint32( buf, (uint)tag ); 162 6191500 : } 163 : 164 : static inline uchar * 165 : fd_pb_append_int32( uchar buf[ fd_pb_varint32_sz_max ], 166 61190 : int value ) { 167 61190 : return fd_pb_append_varint32( buf, (uint)value ); 168 61190 : } 169 : 170 : static inline uchar * 171 : fd_pb_append_int64( uchar buf[ fd_pb_int64_sz_max ], 172 7589 : long value ) { 173 7589 : return fd_pb_append_varint64( buf, (ulong)value ); 174 7589 : } 175 : 176 : static inline uchar * 177 : fd_pb_append_uint32( uchar buf[ fd_pb_uint32_sz_max ], 178 1966206 : uint value ) { 179 1966206 : return fd_pb_append_varint32( buf, value ); 180 1966206 : } 181 : 182 : static inline uchar * 183 : fd_pb_append_uint64( uchar buf[ fd_pb_uint64_sz_max ], 184 1743199 : ulong value ) { 185 1743199 : return fd_pb_append_varint64( buf, value ); 186 1743199 : } 187 : 188 : static inline uchar * 189 : fd_pb_append_sint32( uchar buf[ fd_pb_sint32_sz_max ], 190 0 : int value ) { 191 0 : return fd_pb_append_varint32( buf, fd_int_zz_enc( value ) ); 192 0 : } 193 : 194 : static inline uchar * 195 : fd_pb_append_sint64( uchar buf[ fd_pb_sint64_sz_max ], 196 0 : long value ) { 197 0 : return fd_pb_append_varint64( buf, fd_long_zz_enc( value ) ); 198 0 : } 199 : 200 : static inline uchar * 201 : fd_pb_append_fixed32( uchar buf[ sizeof(uint) ], 202 88 : uint value ) { 203 88 : FD_STORE( uint, buf, value ); 204 88 : return buf+sizeof(uint); 205 88 : } 206 : 207 : static inline uchar * 208 : fd_pb_append_fixed64( uchar buf[ sizeof(ulong) ], 209 1021690 : ulong value ) { 210 1021690 : FD_STORE( ulong, buf, value ); 211 1021690 : return buf+sizeof(ulong); 212 1021690 : } 213 : 214 : #endif /* HEADER_fd_src_ballet_pb_fd_pb_wire_h */