Line data Source code
1 : #include "fd_pb_gen.h"
2 :
3 : uchar *
4 : fd_pb_encode( fd_pb_msgdesc_t const * desc,
5 : void const * msg,
6 : uchar * out,
7 130186 : ulong * out_sz ) {
8 130186 : fd_pb_encoder_t enc[1];
9 130186 : fd_pb_encoder_init( enc, out, *out_sz );
10 130186 : if( FD_UNLIKELY( !desc->encode( enc, msg ) ) ) return NULL;
11 130186 : *out_sz = fd_pb_encoder_out_sz( enc );
12 130186 : fd_pb_encoder_fini( enc );
13 130186 : return out;
14 130186 : }
15 :
16 : void *
17 : fd_pb_decode( fd_pb_msgdesc_t const * desc,
18 : void * msg,
19 : void const * in,
20 : ulong in_sz,
21 71985 : fd_spad_t * spad ) {
22 71985 : fd_pb_inbuf_t buf[1];
23 71985 : fd_pb_inbuf_init( buf, in, in_sz );
24 71985 : if( FD_UNLIKELY( !desc->decode( buf, msg, spad ) ) ) return NULL;
25 71985 : return msg;
26 71985 : }
27 :
28 : /* Scalar decoding */
29 :
30 : static int
31 : dec_varint( fd_pb_tlv_t const * tlv,
32 4255410 : ulong * out ) {
33 4255410 : if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_VARINT ) ) return 0;
34 4255410 : *out = tlv->varint;
35 4255410 : return 1;
36 4255410 : }
37 :
38 : int
39 966218 : fd_pb_dec_bool( fd_pb_tlv_t const * tlv, bool * out ) {
40 966218 : ulong v;
41 966218 : if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
42 966218 : *out = v!=0UL;
43 966218 : return 1;
44 966218 : }
45 :
46 : int
47 36249 : fd_pb_dec_int32( fd_pb_tlv_t const * tlv, int * out ) {
48 36249 : ulong v;
49 36249 : if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
50 36249 : *out = (int)(uint)v;
51 36249 : return 1;
52 36249 : }
53 :
54 : int
55 560659 : fd_pb_dec_uint32( fd_pb_tlv_t const * tlv, uint * out ) {
56 560659 : ulong v;
57 560659 : if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
58 560659 : if( FD_UNLIKELY( v>UINT_MAX ) ) return 0;
59 560659 : *out = (uint)v;
60 560659 : return 1;
61 560659 : }
62 :
63 : int
64 0 : fd_pb_dec_sint32( fd_pb_tlv_t const * tlv, int * out ) {
65 0 : ulong v;
66 0 : if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
67 0 : long s = fd_long_zz_dec( v );
68 0 : if( FD_UNLIKELY( s<INT_MIN || s>INT_MAX ) ) return 0;
69 0 : *out = (int)s;
70 0 : return 1;
71 0 : }
72 :
73 : int
74 1732 : fd_pb_dec_int64( fd_pb_tlv_t const * tlv, long * out ) {
75 1732 : ulong v;
76 1732 : if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
77 1732 : *out = (long)v;
78 1732 : return 1;
79 1732 : }
80 :
81 : int
82 2943992 : fd_pb_dec_uint64( fd_pb_tlv_t const * tlv, ulong * out ) {
83 2943992 : return dec_varint( tlv, out );
84 2943992 : }
85 :
86 : int
87 0 : fd_pb_dec_sint64( fd_pb_tlv_t const * tlv, long * out ) {
88 0 : ulong v;
89 0 : if( FD_UNLIKELY( !dec_varint( tlv, &v ) ) ) return 0;
90 0 : *out = fd_long_zz_dec( v );
91 0 : return 1;
92 0 : }
93 :
94 : int
95 44 : fd_pb_dec_fixed32( fd_pb_tlv_t const * tlv, uint * out ) {
96 44 : if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_I32 ) ) return 0;
97 44 : *out = tlv->i32;
98 44 : return 1;
99 44 : }
100 :
101 : int
102 10100157 : fd_pb_dec_fixed64( fd_pb_tlv_t const * tlv, ulong * out ) {
103 10100157 : if( FD_UNLIKELY( tlv->wire_type!=FD_PB_WIRE_TYPE_I64 ) ) return 0;
104 10100157 : *out = tlv->i64;
105 10100157 : return 1;
106 10100157 : }
107 :
108 : int
109 0 : fd_pb_dec_float( fd_pb_tlv_t const * tlv, float * out ) {
110 0 : union { uint u; float f; } cast;
111 0 : if( FD_UNLIKELY( !fd_pb_dec_fixed32( tlv, &cast.u ) ) ) return 0;
112 0 : *out = cast.f;
113 0 : return 1;
114 0 : }
115 :
116 : int
117 3031 : fd_pb_dec_double( fd_pb_tlv_t const * tlv, double * out ) {
118 3031 : union { ulong u; double d; } cast;
119 3031 : if( FD_UNLIKELY( !fd_pb_dec_fixed64( tlv, &cast.u ) ) ) return 0;
120 3031 : *out = cast.d;
121 3031 : return 1;
122 3031 : }
123 :
124 : /* Repeated fields */
125 :
126 : void *
127 : fd_pb_dec_grow( fd_spad_t * spad,
128 : void * arr,
129 : uint * cnt,
130 : ulong ele_align,
131 11324467 : ulong ele_sz ) {
132 11324467 : uint n = *cnt;
133 11324467 : if( FD_UNLIKELY( n==UINT_MAX ) ) return NULL;
134 11324467 : void * base;
135 11324467 : fd_memcpy( &base, arr, sizeof(void *) );
136 : /* Capacity is the next power of two of n (geometric growth) */
137 11498663 : if( !n || fd_uint_is_pow2( n ) ) {
138 1411120 : ulong cap = n ? 2UL*n : 1UL;
139 1411120 : if( FD_UNLIKELY( fd_spad_alloc_max( spad, ele_align )<cap*ele_sz ) ) return NULL;
140 1411120 : void * p = fd_spad_alloc( spad, ele_align, cap*ele_sz );
141 1411120 : if( n ) fd_memcpy( p, base, n*ele_sz );
142 1411120 : base = p;
143 1411120 : fd_memcpy( arr, &base, sizeof(void *) );
144 1411120 : }
145 11324467 : uchar * ele = (uchar *)base + n*ele_sz;
146 11324467 : memset( ele, 0, ele_sz );
147 11324467 : *cnt = n+1U;
148 11324467 : return ele;
149 11324467 : }
150 :
151 : static ulong
152 93169 : type_sz( int type ) {
153 93169 : switch( type ) {
154 1007 : case FD_PB_GEN_BOOL: return sizeof(bool);
155 0 : case FD_PB_GEN_INT32:
156 25447 : case FD_PB_GEN_UINT32:
157 25447 : case FD_PB_GEN_SINT32:
158 25447 : case FD_PB_GEN_FIXED32: return 4UL;
159 66753 : default: return 8UL;
160 93169 : }
161 93169 : }
162 :
163 : static int
164 : dec_scalar( fd_pb_tlv_t const * tlv,
165 : int type,
166 9803039 : void * out ) {
167 9803039 : switch( type ) {
168 140492 : case FD_PB_GEN_BOOL: return fd_pb_dec_bool ( tlv, out );
169 0 : case FD_PB_GEN_INT32: return fd_pb_dec_int32 ( tlv, out );
170 108518 : case FD_PB_GEN_UINT32: return fd_pb_dec_uint32 ( tlv, out );
171 0 : case FD_PB_GEN_SINT32: return fd_pb_dec_sint32 ( tlv, out );
172 0 : case FD_PB_GEN_INT64: return fd_pb_dec_int64 ( tlv, out );
173 0 : case FD_PB_GEN_UINT64: return fd_pb_dec_uint64 ( tlv, out );
174 0 : case FD_PB_GEN_SINT64: return fd_pb_dec_sint64 ( tlv, out );
175 0 : case FD_PB_GEN_FIXED32: return fd_pb_dec_fixed32( tlv, out );
176 9683919 : case FD_PB_GEN_FIXED64: return fd_pb_dec_fixed64( tlv, out );
177 0 : default: return 0;
178 9803039 : }
179 9803039 : }
180 :
181 : static uint
182 93077 : type_wire( int type ) {
183 93077 : switch( type ) {
184 0 : case FD_PB_GEN_FIXED32: return FD_PB_WIRE_TYPE_I32;
185 66629 : case FD_PB_GEN_FIXED64: return FD_PB_WIRE_TYPE_I64;
186 26343 : default: return FD_PB_WIRE_TYPE_VARINT;
187 93077 : }
188 93077 : }
189 :
190 : int
191 : fd_pb_dec_repeated( fd_pb_inbuf_t * in,
192 : fd_pb_tlv_t const * tlv,
193 : fd_spad_t * spad,
194 : int type,
195 : void * arr,
196 93087 : uint * cnt ) {
197 93087 : ulong ele_sz = type_sz( type );
198 93087 : if( tlv->wire_type!=FD_PB_WIRE_TYPE_LEN ) {
199 0 : void * ele = fd_pb_dec_grow( spad, arr, cnt, ele_sz, ele_sz );
200 0 : if( FD_UNLIKELY( !ele ) ) return 0;
201 0 : return dec_scalar( tlv, type, ele );
202 0 : }
203 :
204 : /* Packed */
205 93087 : fd_pb_inbuf_t sub[1];
206 93087 : if( FD_UNLIKELY( !fd_pb_tlv_submsg( in, tlv, sub ) ) ) return 0;
207 93087 : in->cur = sub->end;
208 93087 : fd_pb_tlv_t vtlv[1] = {{ .wire_type = type_wire( type ), .field_id = tlv->field_id }};
209 9348578 : while( fd_pb_inbuf_sz( sub ) ) {
210 9179004 : switch( vtlv->wire_type ) {
211 246547 : case FD_PB_WIRE_TYPE_VARINT:
212 246547 : if( FD_UNLIKELY( !fd_pb_read_varint( sub, &vtlv->varint ) ) ) return 0;
213 246547 : break;
214 246547 : case FD_PB_WIRE_TYPE_I32:
215 0 : if( FD_UNLIKELY( fd_pb_inbuf_sz( sub )<4UL ) ) return 0;
216 0 : vtlv->varint = 0UL;
217 0 : vtlv->i32 = FD_LOAD( uint, sub->cur );
218 0 : sub->cur += 4UL;
219 0 : break;
220 9159806 : case FD_PB_WIRE_TYPE_I64:
221 9159806 : if( FD_UNLIKELY( fd_pb_inbuf_sz( sub )<8UL ) ) return 0;
222 9159806 : vtlv->i64 = FD_LOAD( ulong, sub->cur );
223 9159806 : sub->cur += 8UL;
224 9159806 : break;
225 9179004 : }
226 9255491 : void * ele = fd_pb_dec_grow( spad, arr, cnt, ele_sz, ele_sz );
227 9255491 : if( FD_UNLIKELY( !ele ) ) return 0;
228 9255491 : if( FD_UNLIKELY( !dec_scalar( vtlv, type, ele ) ) ) return 0;
229 9255491 : }
230 169574 : return 1;
231 93087 : }
232 :
233 : /* Length-delimited fields */
234 :
235 : int
236 : fd_pb_dec_submsg( fd_pb_inbuf_t * in,
237 : fd_pb_tlv_t const * tlv,
238 : fd_spad_t * spad,
239 : fd_pb_msgdesc_t const * desc,
240 3255237 : void * msg ) {
241 3255237 : fd_pb_inbuf_t sub[1];
242 3255237 : if( FD_UNLIKELY( !fd_pb_tlv_submsg( in, tlv, sub ) ) ) return 0;
243 3255237 : in->cur = sub->end;
244 3255237 : return desc->decode( sub, msg, spad );
245 3255237 : }
246 :
247 : int
248 : fd_pb_dec_bytes_ptr( fd_pb_inbuf_t * in,
249 : fd_pb_tlv_t const * tlv,
250 : fd_spad_t * spad,
251 1025743 : fd_pb_bytes_array_t ** out ) {
252 1025743 : uchar const * data = fd_pb_tlv_bytes( in, tlv );
253 1025743 : if( FD_UNLIKELY( !data || tlv->len>UINT_MAX ) ) return 0;
254 1025743 : ulong sz = FD_PB_BYTES_ARRAY_T_ALLOCSIZE( tlv->len );
255 1025743 : if( FD_UNLIKELY( fd_spad_alloc_max( spad, alignof(fd_pb_bytes_array_t) )<sz ) ) return 0;
256 1025743 : fd_pb_bytes_array_t * arr = fd_spad_alloc( spad, alignof(fd_pb_bytes_array_t), sz );
257 1025743 : arr->size = (uint)tlv->len;
258 1025743 : fd_memcpy( arr->bytes, data, tlv->len );
259 1025743 : *out = arr;
260 1025743 : in->cur += tlv->len;
261 1025743 : return 1;
262 1025743 : }
263 :
264 : int
265 : fd_pb_dec_bytes_fixed( fd_pb_inbuf_t * in,
266 : fd_pb_tlv_t const * tlv,
267 : uchar * out,
268 3644693 : ulong sz ) {
269 3644693 : uchar const * data = fd_pb_tlv_bytes( in, tlv );
270 3644693 : if( FD_UNLIKELY( !data ) ) return 0;
271 3644693 : if( !tlv->len ) {
272 : /* Empty bytes decode as all zeros */
273 0 : memset( out, 0, sz );
274 0 : return 1;
275 0 : }
276 3644693 : if( FD_UNLIKELY( tlv->len!=sz ) ) return 0;
277 3644693 : fd_memcpy( out, data, sz );
278 3644693 : in->cur += sz;
279 3644693 : return 1;
280 3644693 : }
281 :
282 : int
283 : fd_pb_dec_bytes_static( fd_pb_inbuf_t * in,
284 : fd_pb_tlv_t const * tlv,
285 : uchar * out,
286 : uint * out_sz,
287 7573 : ulong max ) {
288 7573 : uchar const * data = fd_pb_tlv_bytes( in, tlv );
289 7573 : if( FD_UNLIKELY( !data || tlv->len>max ) ) return 0;
290 7573 : fd_memcpy( out, data, tlv->len );
291 7573 : *out_sz = (uint)tlv->len;
292 7573 : in->cur += tlv->len;
293 7573 : return 1;
294 7573 : }
295 :
296 : int
297 : fd_pb_dec_string_static( fd_pb_inbuf_t * in,
298 : fd_pb_tlv_t const * tlv,
299 : char * out,
300 71530 : ulong max ) {
301 71530 : if( FD_UNLIKELY( !fd_pb_tlv_cstr( in, tlv, out, max ) ) ) return 0;
302 71530 : in->cur += tlv->len;
303 71530 : return 1;
304 71530 : }
305 :
306 : /* Encoding */
307 :
308 : /* lp_close_compact closes a LEN field opened with fd_pb_lp_open and
309 : rewrites the length prefix in its shortest form. */
310 :
311 : static int
312 1182591 : lp_close_compact( fd_pb_encoder_t * enc ) {
313 1182591 : uchar * lp = enc->buf0 + enc->lp_off[ enc->depth-1U ];
314 1182591 : uchar * sub0 = lp + fd_pb_varint32_sz_max;
315 1182591 : ulong sz = (ulong)( enc->cur - sub0 );
316 1182591 : if( FD_UNLIKELY( sz>UINT_MAX ) ) return 0;
317 1182591 : fd_pb_lp_close( enc );
318 1182591 : uchar tmp[ 8 ];
319 1182591 : ulong lp_sz = (ulong)( fd_pb_append_varint32( tmp, (uint)sz ) - tmp );
320 1182591 : fd_memcpy( lp, tmp, lp_sz );
321 1182591 : memmove( lp+lp_sz, sub0, sz );
322 1182591 : enc->cur = lp + lp_sz + sz;
323 1182591 : return 1;
324 1182591 : }
325 :
326 : int
327 : fd_pb_enc_submsg( fd_pb_encoder_t * enc,
328 : uint field_id,
329 : fd_pb_msgdesc_t const * desc,
330 1178639 : void const * msg ) {
331 1178639 : if( FD_UNLIKELY( !fd_pb_submsg_open( enc, field_id ) ) ) return 0;
332 1178639 : if( FD_UNLIKELY( !desc->encode( enc, msg ) ) ) return 0;
333 1178639 : return lp_close_compact( enc );
334 1178639 : }
335 :
336 : int
337 : fd_pb_enc_bytes_ptr( fd_pb_encoder_t * enc,
338 : uint field_id,
339 17058 : fd_pb_bytes_array_t const * bytes ) {
340 17058 : static uchar const empty[1];
341 17058 : if( !bytes ) return !!fd_pb_push_bytes( enc, field_id, empty, 0UL );
342 17058 : return !!fd_pb_push_bytes( enc, field_id, bytes->bytes, bytes->size );
343 17058 : }
344 :
345 : int
346 : fd_pb_enc_packed( fd_pb_encoder_t * enc,
347 : uint field_id,
348 : int type,
349 : void const * arr,
350 2028 : ulong cnt ) {
351 2028 : if( !cnt ) return 1;
352 2016 : if( FD_UNLIKELY( !fd_pb_lp_open( enc, field_id ) ) ) return 0;
353 294386 : for( ulong i=0UL; i<cnt; i++ ) {
354 292384 : if( FD_UNLIKELY( fd_pb_encoder_space( enc )<fd_pb_varint64_sz_max ) ) return 0;
355 292384 : switch( type ) {
356 292382 : case FD_PB_GEN_BOOL: enc->cur = fd_pb_append_bool ( enc->cur, ((bool const *)arr)[i] ); break;
357 0 : case FD_PB_GEN_INT32: enc->cur = fd_pb_append_int64 ( enc->cur, (long)((int const *)arr)[i] ); break;
358 0 : case FD_PB_GEN_UINT32: enc->cur = fd_pb_append_uint32 ( enc->cur, ((uint const *)arr)[i] ); break;
359 0 : case FD_PB_GEN_SINT32: enc->cur = fd_pb_append_sint32 ( enc->cur, ((int const *)arr)[i] ); break;
360 0 : case FD_PB_GEN_INT64: enc->cur = fd_pb_append_int64 ( enc->cur, ((long const *)arr)[i] ); break;
361 0 : case FD_PB_GEN_UINT64: enc->cur = fd_pb_append_uint64 ( enc->cur, ((ulong const *)arr)[i] ); break;
362 0 : case FD_PB_GEN_SINT64: enc->cur = fd_pb_append_sint64 ( enc->cur, ((long const *)arr)[i] ); break;
363 0 : case FD_PB_GEN_FIXED32: enc->cur = fd_pb_append_fixed32( enc->cur, FD_LOAD( uint, (uchar const *)arr+4UL*i ) ); break;
364 0 : case FD_PB_GEN_FIXED64: enc->cur = fd_pb_append_fixed64( enc->cur, FD_LOAD( ulong, (uchar const *)arr+8UL*i ) ); break;
365 0 : default: return 0;
366 292384 : }
367 292384 : }
368 2002 : return lp_close_compact( enc );
369 2016 : }
|