added iOS source code
[wl-app.git] / iOS / Pods / nanopb / 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     if (PB_ATYPE(field->type) == PB_ATYPE_STATIC)
208     {
209         if (PB_LTYPE(field->type) == PB_LTYPE_BYTES)
210         {
211             const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData;
212             return bytes->size == 0;
213         }
214         else if (PB_LTYPE(field->type) == PB_LTYPE_STRING)
215         {
216             return *(const char*)pData == '\0';
217         }
218         else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED_LENGTH_BYTES)
219         {
220             /* Fixed length bytes is only empty if its length is fixed
221              * as 0. Which would be pretty strange, but we can check
222              * it anyway. */
223             return field->data_size == 0;
224         }
225         else if (PB_LTYPE(field->type) == PB_LTYPE_SUBMESSAGE)
226         {
227             /* Check all fields in the submessage to find if any of them
228              * are non-zero. The comparison cannot be done byte-per-byte
229              * because the C struct may contain padding bytes that must
230              * be skipped.
231              */
232             pb_field_iter_t iter;
233             if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData)))
234             {
235                 do
236                 {
237                     if (!pb_check_proto3_default_value(iter.pos, iter.pData))
238                     {
239                         return false;
240                     }
241                 } while (pb_field_iter_next(&iter));
242             }
243             return true;
244         }
245     }
246     
247         {
248             /* Catch-all branch that does byte-per-byte comparison for zero value.
249              *
250              * This is for all pointer fields, and for static PB_LTYPE_VARINT,
251              * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also
252              * callback fields. These all have integer or pointer value which
253              * can be compared with 0.
254              */
255             pb_size_t i;
256             const char *p = (const char*)pData;
257             for (i = 0; i < field->data_size; i++)
258             {
259                 if (p[i] != 0)
260                 {
261                     return false;
262                 }
263             }
264
265             return true;
266         }
267 }
268
269 /* Encode a field with static or pointer allocation, i.e. one whose data
270  * is available to the encoder directly. */
271 static bool checkreturn encode_basic_field(pb_ostream_t *stream,
272     const pb_field_t *field, const void *pData)
273 {
274     pb_encoder_t func;
275     bool implicit_has;
276     const void *pSize = &implicit_has;
277     
278     func = PB_ENCODERS[PB_LTYPE(field->type)];
279     
280     if (field->size_offset)
281     {
282         /* Static optional, repeated or oneof field */
283         pSize = (const char*)pData + field->size_offset;
284     }
285     else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL)
286     {
287         /* Proto3 style field, optional but without explicit has_ field. */
288         implicit_has = !pb_check_proto3_default_value(field, pData);
289     }
290     else
291     {
292         /* Required field, always present */
293         implicit_has = true;
294     }
295
296     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
297     {
298         /* pData is a pointer to the field, which contains pointer to
299          * the data. If the 2nd pointer is NULL, it is interpreted as if
300          * the has_field was false.
301          */
302         pData = *(const void* const*)pData;
303         implicit_has = (pData != NULL);
304     }
305
306     switch (PB_HTYPE(field->type))
307     {
308         case PB_HTYPE_REQUIRED:
309             if (!pData)
310                 PB_RETURN_ERROR(stream, "missing required field");
311             if (!pb_encode_tag_for_field(stream, field))
312                 return false;
313             if (!func(stream, field, pData))
314                 return false;
315             break;
316         
317         case PB_HTYPE_OPTIONAL:
318             if (*(const bool*)pSize)
319             {
320                 if (!pb_encode_tag_for_field(stream, field))
321                     return false;
322             
323                 if (!func(stream, field, pData))
324                     return false;
325             }
326             break;
327         
328         case PB_HTYPE_REPEATED:
329             if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func))
330                 return false;
331             break;
332         
333         case PB_HTYPE_ONEOF:
334             if (*(const pb_size_t*)pSize == field->tag)
335             {
336                 if (!pb_encode_tag_for_field(stream, field))
337                     return false;
338
339                 if (!func(stream, field, pData))
340                     return false;
341             }
342             break;
343             
344         default:
345             PB_RETURN_ERROR(stream, "invalid field type");
346     }
347     
348     return true;
349 }
350
351 /* Encode a field with callback semantics. This means that a user function is
352  * called to provide and encode the actual data. */
353 static bool checkreturn encode_callback_field(pb_ostream_t *stream,
354     const pb_field_t *field, const void *pData)
355 {
356     const pb_callback_t *callback = (const pb_callback_t*)pData;
357     
358 #ifdef PB_OLD_CALLBACK_STYLE
359     const void *arg = callback->arg;
360 #else
361     void * const *arg = &(callback->arg);
362 #endif    
363     
364     if (callback->funcs.encode != NULL)
365     {
366         if (!callback->funcs.encode(stream, field, arg))
367             PB_RETURN_ERROR(stream, "callback error");
368     }
369     return true;
370 }
371
372 /* Encode a single field of any callback or static type. */
373 static bool checkreturn encode_field(pb_ostream_t *stream,
374     const pb_field_t *field, const void *pData)
375 {
376     switch (PB_ATYPE(field->type))
377     {
378         case PB_ATYPE_STATIC:
379         case PB_ATYPE_POINTER:
380             return encode_basic_field(stream, field, pData);
381         
382         case PB_ATYPE_CALLBACK:
383             return encode_callback_field(stream, field, pData);
384         
385         default:
386             PB_RETURN_ERROR(stream, "invalid field type");
387     }
388 }
389
390 /* Default handler for extension fields. Expects to have a pb_field_t
391  * pointer in the extension->type->arg field. */
392 static bool checkreturn default_extension_encoder(pb_ostream_t *stream,
393     const pb_extension_t *extension)
394 {
395     const pb_field_t *field = (const pb_field_t*)extension->type->arg;
396     
397     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
398     {
399         /* For pointer extensions, the pointer is stored directly
400          * in the extension structure. This avoids having an extra
401          * indirection. */
402         return encode_field(stream, field, &extension->dest);
403     }
404     else
405     {
406         return encode_field(stream, field, extension->dest);
407     }
408 }
409
410 /* Walk through all the registered extensions and give them a chance
411  * to encode themselves. */
412 static bool checkreturn encode_extension_field(pb_ostream_t *stream,
413     const pb_field_t *field, const void *pData)
414 {
415     const pb_extension_t *extension = *(const pb_extension_t* const *)pData;
416     PB_UNUSED(field);
417     
418     while (extension)
419     {
420         bool status;
421         if (extension->type->encode)
422             status = extension->type->encode(stream, extension);
423         else
424             status = default_extension_encoder(stream, extension);
425
426         if (!status)
427             return false;
428         
429         extension = extension->next;
430     }
431     
432     return true;
433 }
434
435 /*********************
436  * Encode all fields *
437  *********************/
438
439 static void *pb_const_cast(const void *p)
440 {
441     /* Note: this casts away const, in order to use the common field iterator
442      * logic for both encoding and decoding. */
443     union {
444         void *p1;
445         const void *p2;
446     } t;
447     t.p2 = p;
448     return t.p1;
449 }
450
451 bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
452 {
453     pb_field_iter_t iter;
454     if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct)))
455         return true; /* Empty message type */
456     
457     do {
458         if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION)
459         {
460             /* Special case for the extension field placeholder */
461             if (!encode_extension_field(stream, iter.pos, iter.pData))
462                 return false;
463         }
464         else
465         {
466             /* Regular field */
467             if (!encode_field(stream, iter.pos, iter.pData))
468                 return false;
469         }
470     } while (pb_field_iter_next(&iter));
471     
472     return true;
473 }
474
475 bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
476 {
477     return pb_encode_submessage(stream, fields, src_struct);
478 }
479
480 bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
481 {
482     pb_ostream_t stream = PB_OSTREAM_SIZING;
483     
484     if (!pb_encode(&stream, fields, src_struct))
485         return false;
486     
487     *size = stream.bytes_written;
488     return true;
489 }
490
491 /********************
492  * Helper functions *
493  ********************/
494 bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value)
495 {
496     pb_byte_t buffer[10];
497     size_t i = 0;
498     
499     if (value <= 0x7F)
500     {
501         pb_byte_t v = (pb_byte_t)value;
502         return pb_write(stream, &v, 1);
503     }
504     
505     while (value)
506     {
507         buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80);
508         value >>= 7;
509         i++;
510     }
511     buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
512     
513     return pb_write(stream, buffer, i);
514 }
515
516 bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
517 {
518     uint64_t zigzagged;
519     if (value < 0)
520         zigzagged = ~((uint64_t)value << 1);
521     else
522         zigzagged = (uint64_t)value << 1;
523     
524     return pb_encode_varint(stream, zigzagged);
525 }
526
527 bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
528 {
529     uint32_t val = *(const uint32_t*)value;
530     pb_byte_t bytes[4];
531     bytes[0] = (pb_byte_t)(val & 0xFF);
532     bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
533     bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
534     bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
535     return pb_write(stream, bytes, 4);
536 }
537
538 bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
539 {
540     uint64_t val = *(const uint64_t*)value;
541     pb_byte_t bytes[8];
542     bytes[0] = (pb_byte_t)(val & 0xFF);
543     bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
544     bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
545     bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
546     bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
547     bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
548     bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
549     bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
550     return pb_write(stream, bytes, 8);
551 }
552
553 bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
554 {
555     uint64_t tag = ((uint64_t)field_number << 3) | wiretype;
556     return pb_encode_varint(stream, tag);
557 }
558
559 bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
560 {
561     pb_wire_type_t wiretype;
562     switch (PB_LTYPE(field->type))
563     {
564         case PB_LTYPE_VARINT:
565         case PB_LTYPE_UVARINT:
566         case PB_LTYPE_SVARINT:
567             wiretype = PB_WT_VARINT;
568             break;
569         
570         case PB_LTYPE_FIXED32:
571             wiretype = PB_WT_32BIT;
572             break;
573         
574         case PB_LTYPE_FIXED64:
575             wiretype = PB_WT_64BIT;
576             break;
577         
578         case PB_LTYPE_BYTES:
579         case PB_LTYPE_STRING:
580         case PB_LTYPE_SUBMESSAGE:
581         case PB_LTYPE_FIXED_LENGTH_BYTES:
582             wiretype = PB_WT_STRING;
583             break;
584         
585         default:
586             PB_RETURN_ERROR(stream, "invalid field type");
587     }
588     
589     return pb_encode_tag(stream, wiretype, field->tag);
590 }
591
592 bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
593 {
594     if (!pb_encode_varint(stream, (uint64_t)size))
595         return false;
596     
597     return pb_write(stream, buffer, size);
598 }
599
600 bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
601 {
602     /* First calculate the message size using a non-writing substream. */
603     pb_ostream_t substream = PB_OSTREAM_SIZING;
604     size_t size;
605     bool status;
606     
607     if (!pb_encode(&substream, fields, src_struct))
608     {
609 #ifndef PB_NO_ERRMSG
610         stream->errmsg = substream.errmsg;
611 #endif
612         return false;
613     }
614     
615     size = substream.bytes_written;
616     
617     if (!pb_encode_varint(stream, (uint64_t)size))
618         return false;
619     
620     if (stream->callback == NULL)
621         return pb_write(stream, NULL, size); /* Just sizing */
622     
623     if (stream->bytes_written + size > stream->max_size)
624         PB_RETURN_ERROR(stream, "stream full");
625         
626     /* Use a substream to verify that a callback doesn't write more than
627      * what it did the first time. */
628     substream.callback = stream->callback;
629     substream.state = stream->state;
630     substream.max_size = size;
631     substream.bytes_written = 0;
632 #ifndef PB_NO_ERRMSG
633     substream.errmsg = NULL;
634 #endif
635     
636     status = pb_encode(&substream, fields, src_struct);
637     
638     stream->bytes_written += substream.bytes_written;
639     stream->state = substream.state;
640 #ifndef PB_NO_ERRMSG
641     stream->errmsg = substream.errmsg;
642 #endif
643     
644     if (substream.bytes_written != size)
645         PB_RETURN_ERROR(stream, "submsg size changed");
646     
647     return status;
648 }
649
650 /* Field encoders */
651
652 static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
653 {
654     int64_t value = 0;
655     
656     if (field->data_size == sizeof(int_least8_t))
657         value = *(const int_least8_t*)src;
658     else if (field->data_size == sizeof(int_least16_t))
659         value = *(const int_least16_t*)src;
660     else if (field->data_size == sizeof(int32_t))
661         value = *(const int32_t*)src;
662     else if (field->data_size == sizeof(int64_t))
663         value = *(const int64_t*)src;
664     else
665         PB_RETURN_ERROR(stream, "invalid data_size");
666     
667     return pb_encode_varint(stream, (uint64_t)value);
668 }
669
670 static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
671 {
672     uint64_t value = 0;
673     
674     if (field->data_size == sizeof(uint_least8_t))
675         value = *(const uint_least8_t*)src;
676     else if (field->data_size == sizeof(uint_least16_t))
677         value = *(const uint_least16_t*)src;
678     else if (field->data_size == sizeof(uint32_t))
679         value = *(const uint32_t*)src;
680     else if (field->data_size == sizeof(uint64_t))
681         value = *(const uint64_t*)src;
682     else
683         PB_RETURN_ERROR(stream, "invalid data_size");
684     
685     return pb_encode_varint(stream, value);
686 }
687
688 static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
689 {
690     int64_t value = 0;
691     
692     if (field->data_size == sizeof(int_least8_t))
693         value = *(const int_least8_t*)src;
694     else if (field->data_size == sizeof(int_least16_t))
695         value = *(const int_least16_t*)src;
696     else if (field->data_size == sizeof(int32_t))
697         value = *(const int32_t*)src;
698     else if (field->data_size == sizeof(int64_t))
699         value = *(const int64_t*)src;
700     else
701         PB_RETURN_ERROR(stream, "invalid data_size");
702     
703     return pb_encode_svarint(stream, value);
704 }
705
706 static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
707 {
708     PB_UNUSED(field);
709     return pb_encode_fixed64(stream, src);
710 }
711
712 static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
713 {
714     PB_UNUSED(field);
715     return pb_encode_fixed32(stream, src);
716 }
717
718 static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
719 {
720     const pb_bytes_array_t *bytes = NULL;
721
722     bytes = (const pb_bytes_array_t*)src;
723     
724     if (src == NULL)
725     {
726         /* Treat null pointer as an empty bytes field */
727         return pb_encode_string(stream, NULL, 0);
728     }
729     
730     if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
731         PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size)
732     {
733         PB_RETURN_ERROR(stream, "bytes size exceeded");
734     }
735     
736     return pb_encode_string(stream, bytes->bytes, bytes->size);
737 }
738
739 static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
740 {
741     size_t size = 0;
742     size_t max_size = field->data_size;
743     const char *p = (const char*)src;
744     
745     if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
746         max_size = (size_t)-1;
747
748     if (src == NULL)
749     {
750         size = 0; /* Treat null pointer as an empty string */
751     }
752     else
753     {
754         /* strnlen() is not always available, so just use a loop */
755         while (size < max_size && *p != '\0')
756         {
757             size++;
758             p++;
759         }
760     }
761
762     return pb_encode_string(stream, (const pb_byte_t*)src, size);
763 }
764
765 static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
766 {
767     if (field->ptr == NULL)
768         PB_RETURN_ERROR(stream, "invalid field descriptor");
769     
770     return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
771 }
772
773 static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
774 {
775     return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size);
776 }
777