Fix bugs in proto3 mode encoding of submessages (#256)
[apps/agl-service-can-low-level.git] / pb_encode.c
1 /* pb_encode.c -- encode a protobuf using minimal resources
2  *
3  * 2011 Petteri Aimonen <jpa@kapsi.fi>
4  */
5
6 #include "pb.h"
7 #include "pb_encode.h"
8 #include "pb_common.h"
9
10 /* Use the GCC warn_unused_result attribute to check that all return values
11  * are propagated correctly. On other compilers and gcc before 3.4.0 just
12  * ignore the annotation.
13  */
14 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
15     #define checkreturn
16 #else
17     #define checkreturn __attribute__((warn_unused_result))
18 #endif
19
20 /**************************************
21  * Declarations internal to this file *
22  **************************************/
23 typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn;
24
25 static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
26 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func);
27 static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
28 static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
29 static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
30 static void *pb_const_cast(const void *p);
31 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
32 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
33 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
34 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src);
35 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src);
36 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src);
37 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src);
38 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
39 static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src);
40
41 /* --- Function pointers to field encoders ---
42  * Order in the array must match pb_action_t LTYPE numbering.
43  */
44 static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
45     &pb_enc_varint,
46     &pb_enc_uvarint,
47     &pb_enc_svarint,
48     &pb_enc_fixed32,
49     &pb_enc_fixed64,
50     
51     &pb_enc_bytes,
52     &pb_enc_string,
53     &pb_enc_submessage,
54     NULL, /* extensions */
55     &pb_enc_fixed_length_bytes
56 };
57
58 /*******************************
59  * pb_ostream_t implementation *
60  *******************************/
61
62 static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
63 {
64     size_t i;
65     pb_byte_t *dest = (pb_byte_t*)stream->state;
66     stream->state = dest + count;
67     
68     for (i = 0; i < count; i++)
69         dest[i] = buf[i];
70     
71     return true;
72 }
73
74 pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
75 {
76     pb_ostream_t stream;
77 #ifdef PB_BUFFER_ONLY
78     stream.callback = (void*)1; /* Just a marker value */
79 #else
80     stream.callback = &buf_write;
81 #endif
82     stream.state = buf;
83     stream.max_size = bufsize;
84     stream.bytes_written = 0;
85 #ifndef PB_NO_ERRMSG
86     stream.errmsg = NULL;
87 #endif
88     return stream;
89 }
90
91 bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
92 {
93     if (stream->callback != NULL)
94     {
95         if (stream->bytes_written + count > stream->max_size)
96             PB_RETURN_ERROR(stream, "stream full");
97
98 #ifdef PB_BUFFER_ONLY
99         if (!buf_write(stream, buf, count))
100             PB_RETURN_ERROR(stream, "io error");
101 #else        
102         if (!stream->callback(stream, buf, count))
103             PB_RETURN_ERROR(stream, "io error");
104 #endif
105     }
106     
107     stream->bytes_written += count;
108     return true;
109 }
110
111 /*************************
112  * Encode a single field *
113  *************************/
114
115 /* Encode a static array. Handles the size calculations and possible packing. */
116 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
117                          const void *pData, size_t count, pb_encoder_t func)
118 {
119     size_t i;
120     const void *p;
121     size_t size;
122     
123     if (count == 0)
124         return true;
125
126     if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
127         PB_RETURN_ERROR(stream, "array max size exceeded");
128     
129     /* We always pack arrays if the datatype allows it. */
130     if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
131     {
132         if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
133             return false;
134         
135         /* Determine the total size of packed array. */
136         if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
137         {
138             size = 4 * count;
139         }
140         else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
141         {
142             size = 8 * count;
143         }
144         else
145         { 
146             pb_ostream_t sizestream = PB_OSTREAM_SIZING;
147             p = pData;
148             for (i = 0; i < count; i++)
149             {
150                 if (!func(&sizestream, field, p))
151                     return false;
152                 p = (const char*)p + field->data_size;
153             }
154             size = sizestream.bytes_written;
155         }
156         
157         if (!pb_encode_varint(stream, (uint64_t)size))
158             return false;
159         
160         if (stream->callback == NULL)
161             return pb_write(stream, NULL, size); /* Just sizing.. */
162         
163         /* Write the data */
164         p = pData;
165         for (i = 0; i < count; i++)
166         {
167             if (!func(stream, field, p))
168                 return false;
169             p = (const char*)p + field->data_size;
170         }
171     }
172     else
173     {
174         p = pData;
175         for (i = 0; i < count; i++)
176         {
177             if (!pb_encode_tag_for_field(stream, field))
178                 return false;
179
180             /* Normally the data is stored directly in the array entries, but
181              * for pointer-type string and bytes fields, the array entries are
182              * actually pointers themselves also. So we have to dereference once
183              * more to get to the actual data. */
184             if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
185                 (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
186                  PB_LTYPE(field->type) == PB_LTYPE_BYTES))
187             {
188                 if (!func(stream, field, *(const void* const*)p))
189                     return false;      
190             }
191             else
192             {
193                 if (!func(stream, field, p))
194                     return false;
195             }
196             p = (const char*)p + field->data_size;
197         }
198     }
199     
200     return true;
201 }
202
203 /* In proto3, all fields are optional and are only encoded if their value is "non-zero".
204  * This function implements the check for the zero value. */
205 static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData)
206 {
207     pb_type_t type = field->type;
208     const void *pSize = (const char*)pData + field->size_offset;
209
210     if (PB_HTYPE(type) == PB_HTYPE_REQUIRED)
211     {
212         /* Required proto2 fields inside proto3 submessage, pretty rare case */
213         return false;
214     }
215     else if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
216     {
217         /* Repeated fields inside proto3 submessage: present if count != 0 */
218         return *(const pb_size_t*)pSize == 0;
219     }
220     else if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
221     {
222         /* Oneof fields */
223         return *(const pb_size_t*)pSize == 0;
224     }
225     else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset)
226     {
227         /* Proto2 optional fields inside proto3 submessage */
228         return *(const bool*)pSize == false;
229     }
230
231     /* Rest is proto3 singular fields */
232
233     if (PB_ATYPE(type) == PB_ATYPE_STATIC)
234     {
235         if (PB_LTYPE(type) == PB_LTYPE_BYTES)
236         {
237             const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData;
238             return bytes->size == 0;
239         }
240         else if (PB_LTYPE(type) == PB_LTYPE_STRING)
241         {
242             return *(const char*)pData == '\0';
243         }
244         else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES)
245         {
246             /* Fixed length bytes is only empty if its length is fixed
247              * as 0. Which would be pretty strange, but we can check
248              * it anyway. */
249             return field->data_size == 0;
250         }
251         else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
252         {
253             /* Check all fields in the submessage to find if any of them
254              * are non-zero. The comparison cannot be done byte-per-byte
255              * because the C struct may contain padding bytes that must
256              * be skipped.
257              */
258             pb_field_iter_t iter;
259             if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData)))
260             {
261                 do
262                 {
263                     if (!pb_check_proto3_default_value(iter.pos, iter.pData))
264                     {
265                         return false;
266                     }
267                 } while (pb_field_iter_next(&iter));
268             }
269             return true;
270         }
271     }
272     
273         {
274             /* Catch-all branch that does byte-per-byte comparison for zero value.
275              *
276              * This is for all pointer fields, and for static PB_LTYPE_VARINT,
277              * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also
278              * callback fields. These all have integer or pointer value which
279              * can be compared with 0.
280              */
281             pb_size_t i;
282             const char *p = (const char*)pData;
283             for (i = 0; i < field->data_size; i++)
284             {
285                 if (p[i] != 0)
286                 {
287                     return false;
288                 }
289             }
290
291             return true;
292         }
293 }
294
295 /* Encode a field with static or pointer allocation, i.e. one whose data
296  * is available to the encoder directly. */
297 static bool checkreturn encode_basic_field(pb_ostream_t *stream,
298     const pb_field_t *field, const void *pData)
299 {
300     pb_encoder_t func;
301     bool implicit_has;
302     const void *pSize = &implicit_has;
303     
304     func = PB_ENCODERS[PB_LTYPE(field->type)];
305     
306     if (field->size_offset)
307     {
308         /* Static optional, repeated or oneof field */
309         pSize = (const char*)pData + field->size_offset;
310     }
311     else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL)
312     {
313         /* Proto3 style field, optional but without explicit has_ field. */
314         implicit_has = !pb_check_proto3_default_value(field, pData);
315     }
316     else
317     {
318         /* Required field, always present */
319         implicit_has = true;
320     }
321
322     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
323     {
324         /* pData is a pointer to the field, which contains pointer to
325          * the data. If the 2nd pointer is NULL, it is interpreted as if
326          * the has_field was false.
327          */
328         pData = *(const void* const*)pData;
329         implicit_has = (pData != NULL);
330     }
331
332     switch (PB_HTYPE(field->type))
333     {
334         case PB_HTYPE_REQUIRED:
335             if (!pData)
336                 PB_RETURN_ERROR(stream, "missing required field");
337             if (!pb_encode_tag_for_field(stream, field))
338                 return false;
339             if (!func(stream, field, pData))
340                 return false;
341             break;
342         
343         case PB_HTYPE_OPTIONAL:
344             if (*(const bool*)pSize)
345             {
346                 if (!pb_encode_tag_for_field(stream, field))
347                     return false;
348             
349                 if (!func(stream, field, pData))
350                     return false;
351             }
352             break;
353         
354         case PB_HTYPE_REPEATED:
355             if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func))
356                 return false;
357             break;
358         
359         case PB_HTYPE_ONEOF:
360             if (*(const pb_size_t*)pSize == field->tag)
361             {
362                 if (!pb_encode_tag_for_field(stream, field))
363                     return false;
364
365                 if (!func(stream, field, pData))
366                     return false;
367             }
368             break;
369             
370         default:
371             PB_RETURN_ERROR(stream, "invalid field type");
372     }
373     
374     return true;
375 }
376
377 /* Encode a field with callback semantics. This means that a user function is
378  * called to provide and encode the actual data. */
379 static bool checkreturn encode_callback_field(pb_ostream_t *stream,
380     const pb_field_t *field, const void *pData)
381 {
382     const pb_callback_t *callback = (const pb_callback_t*)pData;
383     
384 #ifdef PB_OLD_CALLBACK_STYLE
385     const void *arg = callback->arg;
386 #else
387     void * const *arg = &(callback->arg);
388 #endif    
389     
390     if (callback->funcs.encode != NULL)
391     {
392         if (!callback->funcs.encode(stream, field, arg))
393             PB_RETURN_ERROR(stream, "callback error");
394     }
395     return true;
396 }
397
398 /* Encode a single field of any callback or static type. */
399 static bool checkreturn encode_field(pb_ostream_t *stream,
400     const pb_field_t *field, const void *pData)
401 {
402     switch (PB_ATYPE(field->type))
403     {
404         case PB_ATYPE_STATIC:
405         case PB_ATYPE_POINTER:
406             return encode_basic_field(stream, field, pData);
407         
408         case PB_ATYPE_CALLBACK:
409             return encode_callback_field(stream, field, pData);
410         
411         default:
412             PB_RETURN_ERROR(stream, "invalid field type");
413     }
414 }
415
416 /* Default handler for extension fields. Expects to have a pb_field_t
417  * pointer in the extension->type->arg field. */
418 static bool checkreturn default_extension_encoder(pb_ostream_t *stream,
419     const pb_extension_t *extension)
420 {
421     const pb_field_t *field = (const pb_field_t*)extension->type->arg;
422     
423     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
424     {
425         /* For pointer extensions, the pointer is stored directly
426          * in the extension structure. This avoids having an extra
427          * indirection. */
428         return encode_field(stream, field, &extension->dest);
429     }
430     else
431     {
432         return encode_field(stream, field, extension->dest);
433     }
434 }
435
436 /* Walk through all the registered extensions and give them a chance
437  * to encode themselves. */
438 static bool checkreturn encode_extension_field(pb_ostream_t *stream,
439     const pb_field_t *field, const void *pData)
440 {
441     const pb_extension_t *extension = *(const pb_extension_t* const *)pData;
442     PB_UNUSED(field);
443     
444     while (extension)
445     {
446         bool status;
447         if (extension->type->encode)
448             status = extension->type->encode(stream, extension);
449         else
450             status = default_extension_encoder(stream, extension);
451
452         if (!status)
453             return false;
454         
455         extension = extension->next;
456     }
457     
458     return true;
459 }
460
461 /*********************
462  * Encode all fields *
463  *********************/
464
465 static void *pb_const_cast(const void *p)
466 {
467     /* Note: this casts away const, in order to use the common field iterator
468      * logic for both encoding and decoding. */
469     union {
470         void *p1;
471         const void *p2;
472     } t;
473     t.p2 = p;
474     return t.p1;
475 }
476
477 bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
478 {
479     pb_field_iter_t iter;
480     if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct)))
481         return true; /* Empty message type */
482     
483     do {
484         if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION)
485         {
486             /* Special case for the extension field placeholder */
487             if (!encode_extension_field(stream, iter.pos, iter.pData))
488                 return false;
489         }
490         else
491         {
492             /* Regular field */
493             if (!encode_field(stream, iter.pos, iter.pData))
494                 return false;
495         }
496     } while (pb_field_iter_next(&iter));
497     
498     return true;
499 }
500
501 bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
502 {
503     return pb_encode_submessage(stream, fields, src_struct);
504 }
505
506 bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
507 {
508     pb_ostream_t stream = PB_OSTREAM_SIZING;
509     
510     if (!pb_encode(&stream, fields, src_struct))
511         return false;
512     
513     *size = stream.bytes_written;
514     return true;
515 }
516
517 /********************
518  * Helper functions *
519  ********************/
520 bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value)
521 {
522     pb_byte_t buffer[10];
523     size_t i = 0;
524     
525     if (value <= 0x7F)
526     {
527         pb_byte_t v = (pb_byte_t)value;
528         return pb_write(stream, &v, 1);
529     }
530     
531     while (value)
532     {
533         buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80);
534         value >>= 7;
535         i++;
536     }
537     buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
538     
539     return pb_write(stream, buffer, i);
540 }
541
542 bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
543 {
544     uint64_t zigzagged;
545     if (value < 0)
546         zigzagged = ~((uint64_t)value << 1);
547     else
548         zigzagged = (uint64_t)value << 1;
549     
550     return pb_encode_varint(stream, zigzagged);
551 }
552
553 bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
554 {
555     uint32_t val = *(const uint32_t*)value;
556     pb_byte_t bytes[4];
557     bytes[0] = (pb_byte_t)(val & 0xFF);
558     bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
559     bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
560     bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
561     return pb_write(stream, bytes, 4);
562 }
563
564 bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
565 {
566     uint64_t val = *(const uint64_t*)value;
567     pb_byte_t bytes[8];
568     bytes[0] = (pb_byte_t)(val & 0xFF);
569     bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
570     bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
571     bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
572     bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
573     bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
574     bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
575     bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
576     return pb_write(stream, bytes, 8);
577 }
578
579 bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
580 {
581     uint64_t tag = ((uint64_t)field_number << 3) | wiretype;
582     return pb_encode_varint(stream, tag);
583 }
584
585 bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
586 {
587     pb_wire_type_t wiretype;
588     switch (PB_LTYPE(field->type))
589     {
590         case PB_LTYPE_VARINT:
591         case PB_LTYPE_UVARINT:
592         case PB_LTYPE_SVARINT:
593             wiretype = PB_WT_VARINT;
594             break;
595         
596         case PB_LTYPE_FIXED32:
597             wiretype = PB_WT_32BIT;
598             break;
599         
600         case PB_LTYPE_FIXED64:
601             wiretype = PB_WT_64BIT;
602             break;
603         
604         case PB_LTYPE_BYTES:
605         case PB_LTYPE_STRING:
606         case PB_LTYPE_SUBMESSAGE:
607         case PB_LTYPE_FIXED_LENGTH_BYTES:
608             wiretype = PB_WT_STRING;
609             break;
610         
611         default:
612             PB_RETURN_ERROR(stream, "invalid field type");
613     }
614     
615     return pb_encode_tag(stream, wiretype, field->tag);
616 }
617
618 bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
619 {
620     if (!pb_encode_varint(stream, (uint64_t)size))
621         return false;
622     
623     return pb_write(stream, buffer, size);
624 }
625
626 bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
627 {
628     /* First calculate the message size using a non-writing substream. */
629     pb_ostream_t substream = PB_OSTREAM_SIZING;
630     size_t size;
631     bool status;
632     
633     if (!pb_encode(&substream, fields, src_struct))
634     {
635 #ifndef PB_NO_ERRMSG
636         stream->errmsg = substream.errmsg;
637 #endif
638         return false;
639     }
640     
641     size = substream.bytes_written;
642     
643     if (!pb_encode_varint(stream, (uint64_t)size))
644         return false;
645     
646     if (stream->callback == NULL)
647         return pb_write(stream, NULL, size); /* Just sizing */
648     
649     if (stream->bytes_written + size > stream->max_size)
650         PB_RETURN_ERROR(stream, "stream full");
651         
652     /* Use a substream to verify that a callback doesn't write more than
653      * what it did the first time. */
654     substream.callback = stream->callback;
655     substream.state = stream->state;
656     substream.max_size = size;
657     substream.bytes_written = 0;
658 #ifndef PB_NO_ERRMSG
659     substream.errmsg = NULL;
660 #endif
661     
662     status = pb_encode(&substream, fields, src_struct);
663     
664     stream->bytes_written += substream.bytes_written;
665     stream->state = substream.state;
666 #ifndef PB_NO_ERRMSG
667     stream->errmsg = substream.errmsg;
668 #endif
669     
670     if (substream.bytes_written != size)
671         PB_RETURN_ERROR(stream, "submsg size changed");
672     
673     return status;
674 }
675
676 /* Field encoders */
677
678 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
679 {
680     int64_t value = 0;
681     
682     if (field->data_size == sizeof(int_least8_t))
683         value = *(const int_least8_t*)src;
684     else if (field->data_size == sizeof(int_least16_t))
685         value = *(const int_least16_t*)src;
686     else if (field->data_size == sizeof(int32_t))
687         value = *(const int32_t*)src;
688     else if (field->data_size == sizeof(int64_t))
689         value = *(const int64_t*)src;
690     else
691         PB_RETURN_ERROR(stream, "invalid data_size");
692     
693     return pb_encode_varint(stream, (uint64_t)value);
694 }
695
696 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
697 {
698     uint64_t value = 0;
699     
700     if (field->data_size == sizeof(uint_least8_t))
701         value = *(const uint_least8_t*)src;
702     else if (field->data_size == sizeof(uint_least16_t))
703         value = *(const uint_least16_t*)src;
704     else if (field->data_size == sizeof(uint32_t))
705         value = *(const uint32_t*)src;
706     else if (field->data_size == sizeof(uint64_t))
707         value = *(const uint64_t*)src;
708     else
709         PB_RETURN_ERROR(stream, "invalid data_size");
710     
711     return pb_encode_varint(stream, value);
712 }
713
714 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
715 {
716     int64_t value = 0;
717     
718     if (field->data_size == sizeof(int_least8_t))
719         value = *(const int_least8_t*)src;
720     else if (field->data_size == sizeof(int_least16_t))
721         value = *(const int_least16_t*)src;
722     else if (field->data_size == sizeof(int32_t))
723         value = *(const int32_t*)src;
724     else if (field->data_size == sizeof(int64_t))
725         value = *(const int64_t*)src;
726     else
727         PB_RETURN_ERROR(stream, "invalid data_size");
728     
729     return pb_encode_svarint(stream, value);
730 }
731
732 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
733 {
734     PB_UNUSED(field);
735     return pb_encode_fixed64(stream, src);
736 }
737
738 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
739 {
740     PB_UNUSED(field);
741     return pb_encode_fixed32(stream, src);
742 }
743
744 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
745 {
746     const pb_bytes_array_t *bytes = NULL;
747
748     bytes = (const pb_bytes_array_t*)src;
749     
750     if (src == NULL)
751     {
752         /* Treat null pointer as an empty bytes field */
753         return pb_encode_string(stream, NULL, 0);
754     }
755     
756     if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
757         PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size)
758     {
759         PB_RETURN_ERROR(stream, "bytes size exceeded");
760     }
761     
762     return pb_encode_string(stream, bytes->bytes, bytes->size);
763 }
764
765 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
766 {
767     size_t size = 0;
768     size_t max_size = field->data_size;
769     const char *p = (const char*)src;
770     
771     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
772         max_size = (size_t)-1;
773
774     if (src == NULL)
775     {
776         size = 0; /* Treat null pointer as an empty string */
777     }
778     else
779     {
780         /* strnlen() is not always available, so just use a loop */
781         while (size < max_size && *p != '\0')
782         {
783             size++;
784             p++;
785         }
786     }
787
788     return pb_encode_string(stream, (const pb_byte_t*)src, size);
789 }
790
791 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
792 {
793     if (field->ptr == NULL)
794         PB_RETURN_ERROR(stream, "invalid field descriptor");
795     
796     return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
797 }
798
799 static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
800 {
801     return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size);
802 }
803