1 /* pb_decode.c -- decode a protobuf using minimal resources
3 * 2011 Petteri Aimonen <jpa@kapsi.fi>
10 const pb_decoder_t PB_DECODERS[16] = {
11 (pb_decoder_t)&pb_dec_uint32,
12 (pb_decoder_t)&pb_dec_sint32,
13 (pb_decoder_t)&pb_dec_fixed32,
14 (pb_decoder_t)&pb_dec_uint64,
15 (pb_decoder_t)&pb_dec_sint64,
16 (pb_decoder_t)&pb_dec_fixed64,
17 (pb_decoder_t)&pb_dec_bool,
18 (pb_decoder_t)&pb_dec_enum,
20 (pb_decoder_t)&pb_dec_float,
21 (pb_decoder_t)&pb_dec_double,
23 (pb_decoder_t)&pb_dec_bytes,
24 (pb_decoder_t)&pb_dec_string,
25 (pb_decoder_t)&pb_dec_submessage
32 bool pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
35 if (stream->bytes_left < count)
38 status = stream->callback(stream, buf, count);
39 stream->bytes_left -= count;
43 static bool buf_read(pb_istream_t *stream, uint8_t *buf, size_t count)
45 uint8_t *source = (uint8_t*)stream->state;
48 memcpy(buf, source, count);
50 stream->state = source + count;
54 pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
57 stream.callback = &buf_read;
59 stream.bytes_left = bufsize;
67 bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
70 if (!pb_decode_varint64(stream, &temp))
76 bool pb_decode_varint64(pb_istream_t *stream, uint64_t *dest)
82 while (bitpos < 64 && pb_read(stream, &byte, 1))
84 *dest |= (byte & 0x7F) << bitpos;
94 bool pb_skip_varint(pb_istream_t *stream)
99 if (!pb_read(stream, &byte, 1))
101 } while (byte & 0x80);
105 bool pb_skip_string(pb_istream_t *stream)
108 if (!pb_decode_varint32(stream, &length))
111 return pb_read(stream, NULL, length);
114 /* Currently all wire type related stuff is kept hidden from
115 * callbacks. They shouldn't need it. It's better for performance
116 * to just assume the correct type and fail safely on corrupt message.
126 static bool skip(pb_istream_t *stream, int wire_type)
130 case WT_VARINT: return pb_skip_varint(stream);
131 case WT_64BIT: return pb_read(stream, NULL, 8);
132 case WT_STRING: return pb_skip_string(stream);
133 case WT_32BIT: return pb_read(stream, NULL, 4);
134 default: return false;
138 /* Read a raw value to buffer, for the purpose of passing it to callback.
139 * Size is maximum size on call, and actual size on return. */
140 static bool read_raw_value(pb_istream_t *stream, int wire_type, uint8_t *buf, size_t *size)
142 size_t max_size = *size;
150 if (*size > max_size) return false;
151 if (!pb_read(stream, buf, 1)) return false;
152 } while (*buf++ & 0x80);
157 return pb_read(stream, buf, 8);
161 return pb_read(stream, buf, 4);
163 default: return false;
167 /* Decode string length from stream and return a substream with limited length */
168 static bool make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
171 if (!pb_decode_varint32(stream, &size))
174 *substream = *stream;
175 if (substream->bytes_left < size)
178 substream->bytes_left = size;
179 stream->bytes_left -= size;
183 bool decode_field(pb_istream_t *stream, int wire_type, const pb_field_t *field, void *dest_struct)
185 pb_decoder_t func = PB_DECODERS[PB_LTYPE(field->type)];
186 void *pData = (char*)dest_struct + field->data_offset;
187 void *pSize = (char*)dest_struct + field->size_offset;
189 switch (PB_HTYPE(field->type))
191 case PB_HTYPE_REQUIRED:
192 return func(stream, field, pData);
194 case PB_HTYPE_OPTIONAL:
195 *(bool*)pSize = true;
196 return func(stream, field, pData);
199 if (wire_type == WT_STRING
200 && PB_LTYPE(field->type) != PB_LTYPE_BYTES
201 && PB_LTYPE(field->type) != PB_LTYPE_STRING
202 && PB_LTYPE(field->type) != PB_LTYPE_SUBMESSAGE)
205 size_t *size = (size_t*)pSize;
206 pb_istream_t substream;
207 if (!make_string_substream(stream, &substream))
210 while (substream.bytes_left && *size < field->array_size)
212 void *pItem = (uint8_t*)pData + field->data_size * (*size);
213 if (!func(stream, field, pItem))
217 return (substream.bytes_left == 0);
222 size_t *size = (size_t*)pSize;
223 void *pItem = (uint8_t*)pData + field->data_size * (*size);
224 if (*size >= field->array_size)
228 return func(stream, field, pItem);
231 case PB_HTYPE_CALLBACK:
232 if (wire_type == WT_STRING)
234 pb_callback_t *pCallback = (pb_callback_t*)pData;
235 pb_istream_t substream;
237 if (!make_string_substream(stream, &substream))
240 while (substream.bytes_left)
242 if (!pCallback->funcs.decode(&substream, field, pCallback->arg))
248 /* Copy the single scalar value to stack.
249 * This is required so that we can limit the stream length,
250 * which in turn allows to use same callback for packed and
251 * not-packed fields. */
252 pb_istream_t substream;
253 pb_callback_t *pCallback = (pb_callback_t*)pData;
255 size_t size = sizeof(buffer);
257 if (!read_raw_value(stream, wire_type, buffer, &size))
259 substream = pb_istream_from_buffer(buffer, size);
261 return pCallback->funcs.decode(&substream, field, pCallback->arg);
269 bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
271 /* Used to check for required fields */
272 uint32_t fields_seen = 0;
275 /* Initialize size/has fields and apply default values */
276 for (i = 0; fields[i].tag != 0; i++)
278 void *pData = (char*)dest_struct + fields[i].data_offset;
279 void *pSize = (char*)dest_struct + fields[i].size_offset;
280 if (PB_HTYPE(fields[i].type) == PB_HTYPE_OPTIONAL)
282 *(bool*)pSize = false;
284 else if (PB_HTYPE(fields[i].type) == PB_HTYPE_ARRAY)
289 if (PB_HTYPE(fields[i].type) != PB_HTYPE_ARRAY &&
290 PB_HTYPE(fields[i].type) != PB_HTYPE_CALLBACK)
292 if (fields[i].ptr != NULL)
294 memcpy(pData, fields[i].ptr, fields[i].data_size);
298 memset(pData, 0, fields[i].data_size);
303 while (stream->bytes_left)
307 if (!pb_decode_varint32(stream, &temp))
311 wire_type = temp & 7;
314 while (fields[i].tag != 0 && fields[i].tag != tag)
319 if (fields[i].tag == 0) /* No match found, skip data */
321 skip(stream, wire_type);
325 fields_seen |= 1 << (i & 31);
327 if (!decode_field(stream, wire_type, &fields[i], dest_struct))
331 /* Check that all required fields (mod 31) were present. */
332 for (i = 0; fields[i].tag != 0; i++)
334 if (PB_HTYPE(fields[i].type) == PB_HTYPE_REQUIRED &&
335 !(fields_seen & (1 << (i & 31))))
346 bool pb_dec_uint32(pb_istream_t *stream, const pb_field_t *field, uint32_t *dest)
348 return pb_decode_varint32(stream, dest);
351 bool pb_dec_sint32(pb_istream_t *stream, const pb_field_t *field, int32_t *dest)
353 uint32_t *x = (uint32_t*)dest;
354 bool status = pb_decode_varint32(stream, x);
355 *x = (*x >> 1) ^ -(int32_t)(*x & 1);
359 bool pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, uint32_t *dest)
361 uint8_t bytes[4] = {0};
362 bool status = pb_read(stream, bytes, 4);
364 #ifdef __BIG_ENDIAN__
365 uint8_t lebytes[4] = {bytes[3], bytes[2], bytes[1], bytes[0]};
366 memcpy(dest, lebytes, 4);
368 memcpy(dest, bytes, 4);
373 bool pb_dec_uint64(pb_istream_t *stream, const pb_field_t *field, uint64_t *dest)
375 return pb_decode_varint64(stream, dest);
378 bool pb_dec_sint64(pb_istream_t *stream, const pb_field_t *field, int64_t *dest)
380 uint64_t *x = (uint64_t*)dest;
381 bool status = pb_decode_varint64(stream, x);
382 *x = (*x >> 1) ^ -(int64_t)(*x & 1);
386 bool pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, uint64_t *dest)
388 uint8_t bytes[8] = {0};
389 bool status = pb_read(stream, bytes, 8);
391 #ifdef __BIG_ENDIAN__
392 uint8_t lebytes[8] = {bytes[7], bytes[6], bytes[5], bytes[4],
393 bytes[3], bytes[2], bytes[1], bytes[0]};
394 memcpy(dest, lebytes, 4);
396 memcpy(dest, bytes, 4);
401 bool pb_dec_bool(pb_istream_t *stream, const pb_field_t *field, bool *dest)
404 bool status = pb_decode_varint32(stream, &temp);
405 *(bool*)dest = !!temp;
409 bool pb_dec_enum(pb_istream_t *stream, const pb_field_t *field, void *dest)
411 /* Enum sizes can vary, copy only data_size amount of bytes. */
413 bool status = pb_decode_varint32(stream, &temp);
414 memcpy(dest, &temp, field->data_size);
418 bool pb_dec_float(pb_istream_t *stream, const pb_field_t *field, float *dest)
420 return pb_read(stream, (uint8_t*)dest, sizeof(float));
423 bool pb_dec_double(pb_istream_t *stream, const pb_field_t *field, double *dest)
425 return pb_read(stream, (uint8_t*)dest, sizeof(double));
428 bool pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, uint8_t *dest)
430 pb_bytes_array_t *x = (pb_bytes_array_t*)dest;
433 if (!pb_decode_varint32(stream, &temp))
437 /* Note: data_size includes the size of the x.size field, too.
438 * Calculate actual size starting from offset. */
439 if (x->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
442 return pb_read(stream, x->bytes, x->size);
445 bool pb_dec_string(pb_istream_t *stream, const pb_field_t *field, uint8_t *dest)
449 if (!pb_decode_varint32(stream, &size))
452 if (size > field->data_size - 1)
455 status = pb_read(stream, (uint8_t*)dest, size);
456 *((uint8_t*)dest + size) = 0;
460 bool pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
462 pb_istream_t substream;
464 if (!make_string_substream(stream, &substream))
467 if (field->ptr == NULL)
470 return pb_decode(&substream, (pb_field_t*)field->ptr, dest);