Start moving the tests into subfolders. Transition to SCons for build system for...
[apps/agl-service-can-low-level.git] / pb_decode.c
1 /* pb_decode.c -- decode a protobuf using minimal resources
2  *
3  * 2011 Petteri Aimonen <jpa@kapsi.fi>
4  */
5
6 /* The warn_unused_result attribute appeared first in gcc-3.4.0 */
7 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
8     #define checkreturn
9 #else
10     /* Verify that we remember to check all return values for proper error propagation */
11     #define checkreturn __attribute__((warn_unused_result))
12 #endif
13
14 #define NANOPB_INTERNALS
15 #include "pb.h"
16 #include "pb_decode.h"
17
18 typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn;
19
20 /* --- Function pointers to field decoders ---
21  * Order in the array must match pb_action_t LTYPE numbering.
22  */
23 static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
24     &pb_dec_varint,
25     &pb_dec_svarint,
26     &pb_dec_fixed32,
27     &pb_dec_fixed64,
28     
29     &pb_dec_bytes,
30     &pb_dec_string,
31     &pb_dec_submessage,
32     NULL /* extensions */
33 };
34
35 /**************
36  * pb_istream *
37  **************/
38
39 static bool checkreturn buf_read(pb_istream_t *stream, uint8_t *buf, size_t count)
40 {
41     uint8_t *source = (uint8_t*)stream->state;
42     stream->state = source + count;
43     
44     if (buf != NULL)
45     {
46         while (count--)
47             *buf++ = *source++;
48     }
49     
50     return true;
51 }
52
53 bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
54 {
55 #ifndef PB_BUFFER_ONLY
56         if (buf == NULL && stream->callback != buf_read)
57         {
58                 /* Skip input bytes */
59                 uint8_t tmp[16];
60                 while (count > 16)
61                 {
62                         if (!pb_read(stream, tmp, 16))
63                                 return false;
64                         
65                         count -= 16;
66                 }
67                 
68                 return pb_read(stream, tmp, count);
69         }
70 #endif
71
72     if (stream->bytes_left < count)
73         PB_RETURN_ERROR(stream, "end-of-stream");
74     
75 #ifndef PB_BUFFER_ONLY
76     if (!stream->callback(stream, buf, count))
77         PB_RETURN_ERROR(stream, "io error");
78 #else
79     if (!buf_read(stream, buf, count))
80         return false;
81 #endif
82     
83     stream->bytes_left -= count;
84     return true;
85 }
86
87 pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
88 {
89     pb_istream_t stream;
90 #ifdef PB_BUFFER_ONLY
91     stream.callback = NULL;
92 #else
93     stream.callback = &buf_read;
94 #endif
95     stream.state = buf;
96     stream.bytes_left = bufsize;
97 #ifndef PB_NO_ERRMSG
98     stream.errmsg = NULL;
99 #endif
100     return stream;
101 }
102
103 /********************
104  * Helper functions *
105  ********************/
106
107 static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
108 {
109     uint8_t byte;
110     uint32_t result;
111     
112     if (!pb_read(stream, &byte, 1))
113         return false;
114     
115     if (!(byte & 0x80))
116     {
117         /* Quick case, 1 byte value */
118         result = byte;
119     }
120     else
121     {
122         /* Multibyte case */
123         uint8_t bitpos = 7;
124         result = byte & 0x7F;
125         
126         do
127         {
128             if (bitpos >= 32)
129                 PB_RETURN_ERROR(stream, "varint overflow");
130             
131             if (!pb_read(stream, &byte, 1))
132                 return false;
133             
134             result |= (uint32_t)(byte & 0x7F) << bitpos;
135             bitpos = (uint8_t)(bitpos + 7);
136         } while (byte & 0x80);
137    }
138    
139    *dest = result;
140    return true;
141 }
142
143 bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
144 {
145     uint8_t byte;
146     uint8_t bitpos = 0;
147     uint64_t result = 0;
148     
149     do
150     {
151         if (bitpos >= 64)
152             PB_RETURN_ERROR(stream, "varint overflow");
153         
154         if (!pb_read(stream, &byte, 1))
155             return false;
156
157         result |= (uint64_t)(byte & 0x7F) << bitpos;
158         bitpos = (uint8_t)(bitpos + 7);
159     } while (byte & 0x80);
160     
161     *dest = result;
162     return true;
163 }
164
165 bool checkreturn pb_skip_varint(pb_istream_t *stream)
166 {
167     uint8_t byte;
168     do
169     {
170         if (!pb_read(stream, &byte, 1))
171             return false;
172     } while (byte & 0x80);
173     return true;
174 }
175
176 bool checkreturn pb_skip_string(pb_istream_t *stream)
177 {
178     uint32_t length;
179     if (!pb_decode_varint32(stream, &length))
180         return false;
181     
182     return pb_read(stream, NULL, length);
183 }
184
185 bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof)
186 {
187     uint32_t temp;
188     *eof = false;
189     *wire_type = (pb_wire_type_t) 0;
190     *tag = 0;
191     
192     if (!pb_decode_varint32(stream, &temp))
193     {
194         if (stream->bytes_left == 0)
195             *eof = true;
196
197         return false;
198     }
199     
200     if (temp == 0)
201     {
202         *eof = true; /* Special feature: allow 0-terminated messages. */
203         return false;
204     }
205     
206     *tag = temp >> 3;
207     *wire_type = (pb_wire_type_t)(temp & 7);
208     return true;
209 }
210
211 bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
212 {
213     switch (wire_type)
214     {
215         case PB_WT_VARINT: return pb_skip_varint(stream);
216         case PB_WT_64BIT: return pb_read(stream, NULL, 8);
217         case PB_WT_STRING: return pb_skip_string(stream);
218         case PB_WT_32BIT: return pb_read(stream, NULL, 4);
219         default: PB_RETURN_ERROR(stream, "invalid wire_type");
220     }
221 }
222
223 /* Read a raw value to buffer, for the purpose of passing it to callback as
224  * a substream. Size is maximum size on call, and actual size on return.
225  */
226 static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, uint8_t *buf, size_t *size)
227 {
228     size_t max_size = *size;
229     switch (wire_type)
230     {
231         case PB_WT_VARINT:
232             *size = 0;
233             do
234             {
235                 (*size)++;
236                 if (*size > max_size) return false;
237                 if (!pb_read(stream, buf, 1)) return false;
238             } while (*buf++ & 0x80);
239             return true;
240             
241         case PB_WT_64BIT:
242             *size = 8;
243             return pb_read(stream, buf, 8);
244         
245         case PB_WT_32BIT:
246             *size = 4;
247             return pb_read(stream, buf, 4);
248         
249         default: PB_RETURN_ERROR(stream, "invalid wire_type");
250     }
251 }
252
253 /* Decode string length from stream and return a substream with limited length.
254  * Remember to close the substream using pb_close_string_substream().
255  */
256 bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
257 {
258     uint32_t size;
259     if (!pb_decode_varint32(stream, &size))
260         return false;
261     
262     *substream = *stream;
263     if (substream->bytes_left < size)
264         PB_RETURN_ERROR(stream, "parent stream too short");
265     
266     substream->bytes_left = size;
267     stream->bytes_left -= size;
268     return true;
269 }
270
271 void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream)
272 {
273     stream->state = substream->state;
274
275 #ifndef PB_NO_ERRMSG
276     stream->errmsg = substream->errmsg;
277 #endif
278 }
279
280 /* Iterator for pb_field_t list */
281 typedef struct {
282     const pb_field_t *start; /* Start of the pb_field_t array */
283     const pb_field_t *pos; /* Current position of the iterator */
284     unsigned field_index; /* Zero-based index of the field. */
285     unsigned required_field_index; /* Zero-based index that counts only the required fields */
286     void *dest_struct; /* Pointer to the destination structure to decode to */
287     void *pData; /* Pointer where to store current field value */
288     void *pSize; /* Pointer where to store the size of current array field */
289 } pb_field_iterator_t;
290
291 static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct)
292 {
293     iter->start = iter->pos = fields;
294     iter->field_index = 0;
295     iter->required_field_index = 0;
296     iter->pData = (char*)dest_struct + iter->pos->data_offset;
297     iter->pSize = (char*)iter->pData + iter->pos->size_offset;
298     iter->dest_struct = dest_struct;
299 }
300
301 static bool pb_field_next(pb_field_iterator_t *iter)
302 {
303     bool notwrapped = true;
304     size_t prev_size = iter->pos->data_size;
305     
306     if (PB_ATYPE(iter->pos->type) == PB_ATYPE_STATIC &&
307         PB_HTYPE(iter->pos->type) == PB_HTYPE_REPEATED)
308     {
309         prev_size *= iter->pos->array_size;
310     }
311     
312     if (iter->pos->tag == 0)
313         return false; /* Only happens with empty message types */
314     
315     if (PB_HTYPE(iter->pos->type) == PB_HTYPE_REQUIRED)
316         iter->required_field_index++;
317     
318     iter->pos++;
319     iter->field_index++;
320     if (iter->pos->tag == 0)
321     {
322         iter->pos = iter->start;
323         iter->field_index = 0;
324         iter->required_field_index = 0;
325         iter->pData = iter->dest_struct;
326         prev_size = 0;
327         notwrapped = false;
328     }
329     
330     iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset;
331     iter->pSize = (char*)iter->pData + iter->pos->size_offset;
332     return notwrapped;
333 }
334
335 static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag)
336 {
337     unsigned start = iter->field_index;
338     
339     do {
340         if (iter->pos->tag == tag &&
341             PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION)
342         {
343             return true;
344         }
345         pb_field_next(iter);
346     } while (iter->field_index != start);
347     
348     return false;
349 }
350
351 /*************************
352  * Decode a single field *
353  *************************/
354
355 static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
356 {
357     pb_type_t type;
358     pb_decoder_t func;
359     
360     type = iter->pos->type;
361     func = PB_DECODERS[PB_LTYPE(type)];
362
363     switch (PB_HTYPE(type))
364     {
365         case PB_HTYPE_REQUIRED:
366             return func(stream, iter->pos, iter->pData);
367             
368         case PB_HTYPE_OPTIONAL:
369             *(bool*)iter->pSize = true;
370             return func(stream, iter->pos, iter->pData);
371     
372         case PB_HTYPE_REPEATED:
373             if (wire_type == PB_WT_STRING
374                 && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
375             {
376                 /* Packed array */
377                 bool status = true;
378                 size_t *size = (size_t*)iter->pSize;
379                 pb_istream_t substream;
380                 if (!pb_make_string_substream(stream, &substream))
381                     return false;
382                 
383                 while (substream.bytes_left && *size < iter->pos->array_size)
384                 {
385                     void *pItem = (uint8_t*)iter->pData + iter->pos->data_size * (*size);
386                     if (!func(&substream, iter->pos, pItem))
387                     {
388                         status = false;
389                         break;
390                     }
391                     (*size)++;
392                 }
393                 pb_close_string_substream(stream, &substream);
394                 
395                 if (substream.bytes_left != 0)
396                     PB_RETURN_ERROR(stream, "array overflow");
397                 
398                 return status;
399             }
400             else
401             {
402                 /* Repeated field */
403                 size_t *size = (size_t*)iter->pSize;
404                 void *pItem = (uint8_t*)iter->pData + iter->pos->data_size * (*size);
405                 if (*size >= iter->pos->array_size)
406                     PB_RETURN_ERROR(stream, "array overflow");
407                 
408                 (*size)++;
409                 return func(stream, iter->pos, pItem);
410             }
411
412         default:
413             PB_RETURN_ERROR(stream, "invalid field type");
414     }
415 }
416
417 static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
418 {
419     pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
420     
421 #ifdef PB_OLD_CALLBACK_STYLE
422     void *arg = pCallback->arg;
423 #else
424     void **arg = &(pCallback->arg);
425 #endif
426     
427     if (pCallback->funcs.decode == NULL)
428         return pb_skip_field(stream, wire_type);
429     
430     if (wire_type == PB_WT_STRING)
431     {
432         pb_istream_t substream;
433         
434         if (!pb_make_string_substream(stream, &substream))
435             return false;
436         
437         do
438         {
439             if (!pCallback->funcs.decode(&substream, iter->pos, arg))
440                 PB_RETURN_ERROR(stream, "callback failed");
441         } while (substream.bytes_left);
442         
443         pb_close_string_substream(stream, &substream);
444         return true;
445     }
446     else
447     {
448         /* Copy the single scalar value to stack.
449          * This is required so that we can limit the stream length,
450          * which in turn allows to use same callback for packed and
451          * not-packed fields. */
452         pb_istream_t substream;
453         uint8_t buffer[10];
454         size_t size = sizeof(buffer);
455         
456         if (!read_raw_value(stream, wire_type, buffer, &size))
457             return false;
458         substream = pb_istream_from_buffer(buffer, size);
459         
460         return pCallback->funcs.decode(&substream, iter->pos, arg);
461     }
462 }
463
464 static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
465 {
466     switch (PB_ATYPE(iter->pos->type))
467     {
468         case PB_ATYPE_STATIC:
469             return decode_static_field(stream, wire_type, iter);
470         
471         case PB_ATYPE_CALLBACK:
472             return decode_callback_field(stream, wire_type, iter);
473         
474         default:
475             PB_RETURN_ERROR(stream, "invalid field type");
476     }
477 }
478
479 /* Default handler for extension fields. Expects a pb_field_t structure
480  * in extension->type->arg. */
481 static bool checkreturn default_extension_handler(pb_istream_t *stream,
482     pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type)
483 {
484     const pb_field_t *field = (const pb_field_t*)extension->type->arg;
485     pb_field_iterator_t iter;
486     bool dummy;
487     
488     if (field->tag != tag)
489         return true;
490     
491     iter.start = field;
492     iter.pos = field;
493     iter.field_index = 0;
494     iter.required_field_index = 0;
495     iter.dest_struct = extension->dest;
496     iter.pData = extension->dest;
497     iter.pSize = &dummy;
498     
499     return decode_field(stream, wire_type, &iter);
500 }
501
502 /* Try to decode an unknown field as an extension field. Tries each extension
503  * decoder in turn, until one of them handles the field or loop ends. */
504 static bool checkreturn decode_extension(pb_istream_t *stream,
505     uint32_t tag, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
506 {
507     pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
508     size_t pos = stream->bytes_left;
509     
510     while (extension && pos == stream->bytes_left)
511     {
512         bool status;
513         if (extension->type->decode)
514             status = extension->type->decode(stream, extension, tag, wire_type);
515         else
516             status = default_extension_handler(stream, extension, tag, wire_type);
517
518         if (!status)
519             return false;
520         
521         extension = extension->next;
522     }
523     
524     return true;
525 }
526
527 /* Step through the iterator until an extension field is found or until all
528  * entries have been checked. There can be only one extension field per
529  * message. Returns false if no extension field is found. */
530 static bool checkreturn find_extension_field(pb_field_iterator_t *iter)
531 {
532     unsigned start = iter->field_index;
533     
534     do {
535         if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION)
536             return true;
537         pb_field_next(iter);
538     } while (iter->field_index != start);
539     
540     return false;
541 }
542
543 /* Initialize message fields to default values, recursively */
544 static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct)
545 {
546     pb_field_iterator_t iter;
547     pb_field_init(&iter, fields, dest_struct);
548     
549     /* Initialize size/has fields and apply default values */
550     do
551     {
552         pb_type_t type;
553         type = iter.pos->type;
554     
555         if (iter.pos->tag == 0)
556             continue;
557         
558         if (PB_ATYPE(type) == PB_ATYPE_STATIC)
559         {
560             /* Initialize the size field for optional/repeated fields to 0. */
561             if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL)
562             {
563                 *(bool*)iter.pSize = false;
564             }
565             else if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
566             {
567                 *(size_t*)iter.pSize = 0;
568                 continue; /* Array is empty, no need to initialize contents */
569             }
570             
571             /* Initialize field contents to default value */
572             if (PB_LTYPE(iter.pos->type) == PB_LTYPE_SUBMESSAGE)
573             {
574                 pb_message_set_to_defaults((const pb_field_t *) iter.pos->ptr, iter.pData);
575             }
576             else if (iter.pos->ptr != NULL)
577             {
578                 memcpy(iter.pData, iter.pos->ptr, iter.pos->data_size);
579             }
580             else
581             {
582                 memset(iter.pData, 0, iter.pos->data_size);
583             }
584         }
585         else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
586         {
587             continue; /* Don't overwrite callback */
588         }
589     } while (pb_field_next(&iter));
590 }
591
592 /*********************
593  * Decode all fields *
594  *********************/
595
596 bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
597 {
598     uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */
599     uint32_t extension_range_start = 0;
600     pb_field_iterator_t iter;
601     
602     pb_field_init(&iter, fields, dest_struct);
603     
604     while (stream->bytes_left)
605     {
606         uint32_t tag;
607         pb_wire_type_t wire_type;
608         bool eof;
609         
610         if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
611         {
612             if (eof)
613                 break;
614             else
615                 return false;
616         }
617         
618         if (!pb_field_find(&iter, tag))
619         {
620             /* No match found, check if it matches an extension. */
621             if (tag >= extension_range_start)
622             {
623                 if (!find_extension_field(&iter))
624                     extension_range_start = (uint32_t)-1;
625                 else
626                     extension_range_start = iter.pos->tag;
627                 
628                 if (tag >= extension_range_start)
629                 {
630                     size_t pos = stream->bytes_left;
631                 
632                     if (!decode_extension(stream, tag, wire_type, &iter))
633                         return false;
634                     
635                     if (pos != stream->bytes_left)
636                     {
637                         /* The field was handled */
638                         continue;                    
639                     }
640                 }
641             }
642         
643             /* No match found, skip data */
644             if (!pb_skip_field(stream, wire_type))
645                 return false;
646             continue;
647         }
648         
649         if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED
650             && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
651         {
652             fields_seen[iter.required_field_index >> 3] |= (uint8_t)(1 << (iter.required_field_index & 7));
653         }
654             
655         if (!decode_field(stream, wire_type, &iter))
656             return false;
657     }
658     
659     /* Check that all required fields were present. */
660     {
661         /* First figure out the number of required fields by
662          * seeking to the end of the field array. Usually we
663          * are already close to end after decoding.
664          */
665         unsigned req_field_count;
666         pb_type_t last_type;
667         unsigned i;
668         do {
669             req_field_count = iter.required_field_index;
670             last_type = iter.pos->type;
671         } while (pb_field_next(&iter));
672         
673         /* Fixup if last field was also required. */
674         if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag)
675             req_field_count++;
676         
677         /* Check the whole bytes */
678         for (i = 0; i < (req_field_count >> 3); i++)
679         {
680             if (fields_seen[i] != 0xFF)
681                 PB_RETURN_ERROR(stream, "missing required field");
682         }
683         
684         /* Check the remaining bits */
685         if (fields_seen[req_field_count >> 3] != (0xFF >> (8 - (req_field_count & 7))))
686             PB_RETURN_ERROR(stream, "missing required field");
687     }
688     
689     return true;
690 }
691
692 bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
693 {
694     pb_message_set_to_defaults(fields, dest_struct);
695     return pb_decode_noinit(stream, fields, dest_struct);
696 }
697
698 bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
699 {
700     pb_istream_t substream;
701     bool status;
702     
703     if (!pb_make_string_substream(stream, &substream))
704         return false;
705     
706     status = pb_decode(&substream, fields, dest_struct);
707     pb_close_string_substream(stream, &substream);
708     return status;
709 }
710
711 /* Field decoders */
712
713 bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest)
714 {
715     uint64_t value;
716     if (!pb_decode_varint(stream, &value))
717         return false;
718     
719     if (value & 1)
720         *dest = (int64_t)(~(value >> 1));
721     else
722         *dest = (int64_t)(value >> 1);
723     
724     return true;
725 }
726
727 bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
728 {
729     #ifdef __BIG_ENDIAN__
730     uint8_t *bytes = (uint8_t*)dest;
731     uint8_t lebytes[4];
732     
733     if (!pb_read(stream, lebytes, 4))
734         return false;
735     
736     bytes[0] = lebytes[3];
737     bytes[1] = lebytes[2];
738     bytes[2] = lebytes[1];
739     bytes[3] = lebytes[0];
740     return true;
741     #else
742     return pb_read(stream, (uint8_t*)dest, 4);
743     #endif   
744 }
745
746 bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
747 {
748     #ifdef __BIG_ENDIAN__
749     uint8_t *bytes = (uint8_t*)dest;
750     uint8_t lebytes[8];
751     
752     if (!pb_read(stream, lebytes, 8))
753         return false;
754     
755     bytes[0] = lebytes[7];
756     bytes[1] = lebytes[6];
757     bytes[2] = lebytes[5];
758     bytes[3] = lebytes[4];
759     bytes[4] = lebytes[3];
760     bytes[5] = lebytes[2];
761     bytes[6] = lebytes[1];
762     bytes[7] = lebytes[0];
763     return true;
764     #else
765     return pb_read(stream, (uint8_t*)dest, 8);
766     #endif   
767 }
768
769 bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
770 {
771     uint64_t value;
772     if (!pb_decode_varint(stream, &value))
773         return false;
774     
775     switch (field->data_size)
776     {
777         case 1: *(uint8_t*)dest = (uint8_t)value; break;
778         case 2: *(uint16_t*)dest = (uint16_t)value; break;
779         case 4: *(uint32_t*)dest = (uint32_t)value; break;
780         case 8: *(uint64_t*)dest = value; break;
781         default: PB_RETURN_ERROR(stream, "invalid data_size");
782     }
783     
784     return true;
785 }
786
787 bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
788 {
789     int64_t value;
790     if (!pb_decode_svarint(stream, &value))
791         return false;
792     
793     switch (field->data_size)
794     {
795         case 4: *(int32_t*)dest = (int32_t)value; break;
796         case 8: *(int64_t*)dest = value; break;
797         default: PB_RETURN_ERROR(stream, "invalid data_size");
798     }
799     
800     return true;
801 }
802
803 bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
804 {
805     UNUSED(field);
806     return pb_decode_fixed32(stream, dest);
807 }
808
809 bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
810 {
811     UNUSED(field);
812     return pb_decode_fixed64(stream, dest);
813 }
814
815 bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
816 {
817     pb_bytes_array_t *x = (pb_bytes_array_t*)dest;
818     
819     uint32_t temp;
820     if (!pb_decode_varint32(stream, &temp))
821         return false;
822     x->size = temp;
823     
824     /* Check length, noting the space taken by the size_t header. */
825     if (x->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
826         PB_RETURN_ERROR(stream, "bytes overflow");
827     
828     return pb_read(stream, x->bytes, x->size);
829 }
830
831 bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest)
832 {
833     uint32_t size;
834     bool status;
835     if (!pb_decode_varint32(stream, &size))
836         return false;
837     
838     /* Check length, noting the null terminator */
839     if (size + 1 > field->data_size)
840         PB_RETURN_ERROR(stream, "string overflow");
841     
842     status = pb_read(stream, (uint8_t*)dest, size);
843     *((uint8_t*)dest + size) = 0;
844     return status;
845 }
846
847 bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
848 {
849     bool status;
850     pb_istream_t substream;
851     const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr;
852     
853     if (!pb_make_string_substream(stream, &substream))
854         return false;
855     
856     if (field->ptr == NULL)
857         PB_RETURN_ERROR(stream, "invalid field descriptor");
858     
859     /* New array entries need to be initialized, while required and optional
860      * submessages have already been initialized in the top-level pb_decode. */
861     if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
862         status = pb_decode(&substream, submsg_fields, dest);
863     else
864         status = pb_decode_noinit(&substream, submsg_fields, dest);
865     
866     pb_close_string_substream(stream, &substream);
867     return status;
868 }