diff options
Diffstat (limited to 'pb_encode.c')
-rw-r--r-- | pb_encode.c | 436 |
1 files changed, 117 insertions, 319 deletions
diff --git a/pb_encode.c b/pb_encode.c index 089172c..dc5a273 100644 --- a/pb_encode.c +++ b/pb_encode.c @@ -5,7 +5,6 @@ #include "pb.h" #include "pb_encode.h" -#include "pb_common.h" /* Use the GCC warn_unused_result attribute to check that all return values * are propagated correctly. On other compilers and gcc before 3.4.0 just @@ -22,12 +21,11 @@ **************************************/ typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; -static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count); static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); -static void *pb_const_cast(const void *p); static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); @@ -36,17 +34,6 @@ static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *f static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); - -#ifdef PB_WITHOUT_64BIT -#define pb_int64_t int32_t -#define pb_uint64_t uint32_t - -static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value); -#else -#define pb_int64_t int64_t -#define pb_uint64_t uint64_t -#endif /* --- Function pointers to field encoders --- * Order in the array must match pb_action_t LTYPE numbering. @@ -61,27 +48,25 @@ static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { &pb_enc_bytes, &pb_enc_string, &pb_enc_submessage, - NULL, /* extensions */ - &pb_enc_fixed_length_bytes + NULL /* extensions */ }; /******************************* * pb_ostream_t implementation * *******************************/ -static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +static bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count) { - size_t i; - pb_byte_t *dest = (pb_byte_t*)stream->state; + uint8_t *dest = (uint8_t*)stream->state; stream->state = dest + count; - for (i = 0; i < count; i++) - dest[i] = buf[i]; + while (count--) + *dest++ = *buf++; return true; } -pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +pb_ostream_t pb_ostream_from_buffer(uint8_t *buf, size_t bufsize) { pb_ostream_t stream; #ifdef PB_BUFFER_ONLY @@ -98,7 +83,7 @@ pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) return stream; } -bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +bool checkreturn pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count) { if (stream->callback != NULL) { @@ -164,7 +149,7 @@ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *fie size = sizestream.bytes_written; } - if (!pb_encode_varint(stream, (pb_uint64_t)size)) + if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) @@ -196,7 +181,7 @@ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *fie PB_LTYPE(field->type) == PB_LTYPE_BYTES)) { if (!func(stream, field, *(const void* const*)p)) - return false; + return false; } else { @@ -210,124 +195,21 @@ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *fie return true; } -/* In proto3, all fields are optional and are only encoded if their value is "non-zero". - * This function implements the check for the zero value. */ -static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) -{ - pb_type_t type = field->type; - const void *pSize = (const char*)pData + field->size_offset; - - if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) - { - /* Required proto2 fields inside proto3 submessage, pretty rare case */ - return false; - } - else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) - { - /* Repeated fields inside proto3 submessage: present if count != 0 */ - return *(const pb_size_t*)pSize == 0; - } - else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - /* Oneof fields */ - return *(const pb_size_t*)pSize == 0; - } - else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) - { - /* Proto2 optional fields inside proto3 submessage */ - return *(const bool*)pSize == false; - } - - /* Rest is proto3 singular fields */ - - if (PB_ATYPE(type) == PB_ATYPE_STATIC) - { - if (PB_LTYPE(type) == PB_LTYPE_BYTES) - { - const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; - return bytes->size == 0; - } - else if (PB_LTYPE(type) == PB_LTYPE_STRING) - { - return *(const char*)pData == '\0'; - } - else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) - { - /* Fixed length bytes is only empty if its length is fixed - * as 0. Which would be pretty strange, but we can check - * it anyway. */ - return field->data_size == 0; - } - else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) - { - /* Check all fields in the submessage to find if any of them - * are non-zero. The comparison cannot be done byte-per-byte - * because the C struct may contain padding bytes that must - * be skipped. - */ - pb_field_iter_t iter; - if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) - { - do - { - if (!pb_check_proto3_default_value(iter.pos, iter.pData)) - { - return false; - } - } while (pb_field_iter_next(&iter)); - } - return true; - } - } - - { - /* Catch-all branch that does byte-per-byte comparison for zero value. - * - * This is for all pointer fields, and for static PB_LTYPE_VARINT, - * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also - * callback fields. These all have integer or pointer value which - * can be compared with 0. - */ - pb_size_t i; - const char *p = (const char*)pData; - for (i = 0; i < field->data_size; i++) - { - if (p[i] != 0) - { - return false; - } - } - - return true; - } -} - /* Encode a field with static or pointer allocation, i.e. one whose data * is available to the encoder directly. */ static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData) { pb_encoder_t func; - bool implicit_has; - const void *pSize = &implicit_has; + const void *pSize; + bool implicit_has = true; func = PB_ENCODERS[PB_LTYPE(field->type)]; if (field->size_offset) - { - /* Static optional, repeated or oneof field */ pSize = (const char*)pData + field->size_offset; - } - else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) - { - /* Proto3 style field, optional but without explicit has_ field. */ - implicit_has = !pb_check_proto3_default_value(field, pData); - } else - { - /* Required field, always present */ - implicit_has = true; - } + pSize = &implicit_has; if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { @@ -335,6 +217,7 @@ static bool checkreturn encode_basic_field(pb_ostream_t *stream, * the data. If the 2nd pointer is NULL, it is interpreted as if * the has_field was false. */ + pData = *(const void* const*)pData; implicit_has = (pData != NULL); } @@ -361,29 +244,11 @@ static bool checkreturn encode_basic_field(pb_ostream_t *stream, } break; - case PB_HTYPE_REPEATED: { - pb_size_t count; - if (field->size_offset != 0) { - count = *(const pb_size_t*)pSize; - } else { - count = field->array_size; - } - if (!encode_array(stream, field, pData, count, func)) + case PB_HTYPE_REPEATED: + if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) return false; break; - } - case PB_HTYPE_ONEOF: - if (*(const pb_size_t*)pSize == field->tag) - { - if (!pb_encode_tag_for_field(stream, field)) - return false; - - if (!func(stream, field, pData)) - return false; - } - break; - default: PB_RETURN_ERROR(stream, "invalid field type"); } @@ -436,18 +301,7 @@ static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension) { const pb_field_t *field = (const pb_field_t*)extension->type->arg; - - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { - /* For pointer extensions, the pointer is stored directly - * in the extension structure. This avoids having an extra - * indirection. */ - return encode_field(stream, field, &extension->dest); - } - else - { - return encode_field(stream, field, extension->dest); - } + return encode_field(stream, field, extension->dest); } /* Walk through all the registered extensions and give them a chance @@ -456,7 +310,7 @@ static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData) { const pb_extension_t *extension = *(const pb_extension_t* const *)pData; - PB_UNUSED(field); + UNUSED(field); while (extension) { @@ -479,38 +333,42 @@ static bool checkreturn encode_extension_field(pb_ostream_t *stream, * Encode all fields * *********************/ -static void *pb_const_cast(const void *p) -{ - /* Note: this casts away const, in order to use the common field iterator - * logic for both encoding and decoding. */ - union { - void *p1; - const void *p2; - } t; - t.p2 = p; - return t.p1; -} - bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { - pb_field_iter_t iter; - if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) - return true; /* Empty message type */ + const pb_field_t *field = fields; + const void *pData = src_struct; + size_t prev_size = 0; - do { - if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) + while (field->tag != 0) + { + pData = (const char*)pData + prev_size + field->data_offset; + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + prev_size = sizeof(const void*); + else + prev_size = field->data_size; + + /* Special case for static arrays */ + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + { + prev_size *= field->array_size; + } + + if (PB_LTYPE(field->type) == PB_LTYPE_EXTENSION) { /* Special case for the extension field placeholder */ - if (!encode_extension_field(stream, iter.pos, iter.pData)) + if (!encode_extension_field(stream, field, pData)) return false; } else { /* Regular field */ - if (!encode_field(stream, iter.pos, iter.pData)) + if (!encode_field(stream, field, pData)) return false; } - } while (pb_field_iter_next(&iter)); + + field++; + } return true; } @@ -520,16 +378,6 @@ bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const return pb_encode_submessage(stream, fields, src_struct); } -bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) -{ - const pb_byte_t zero = 0; - - if (!pb_encode(stream, fields, src_struct)) - return false; - - return pb_write(stream, &zero, 1); -} - bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) { pb_ostream_t stream = PB_OSTREAM_SIZING; @@ -544,47 +392,17 @@ bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *sr /******************** * Helper functions * ********************/ - -#ifdef PB_WITHOUT_64BIT -bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value) -{ - pb_byte_t buffer[10]; - size_t i = 0; - size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */ - - while (value) - { - buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); - value >>= 7; - if (compensation) - { - /* re-set all the compensation bits we can or need */ - size_t bits = compensation > 7 ? 7 : compensation; - value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); /* set the number of bits needed on the lowest of the most significant 7 bits */ - compensation -= bits; - } - i++; - } - buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ - - return pb_write(stream, buffer, i); -} -#endif - -bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value) { - pb_byte_t buffer[10]; + uint8_t buffer[10]; size_t i = 0; - if (value <= 0x7F) - { - pb_byte_t v = (pb_byte_t)value; - return pb_write(stream, &v, 1); - } + if (value == 0) + return pb_write(stream, (uint8_t*)&value, 1); while (value) { - buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + buffer[i] = (uint8_t)((value & 0x7F) | 0x80); value >>= 7; i++; } @@ -593,48 +411,54 @@ bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) return pb_write(stream, buffer, i); } -bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value) { - pb_uint64_t zigzagged; + uint64_t zigzagged; if (value < 0) - zigzagged = ~((pb_uint64_t)value << 1); + zigzagged = ~((uint64_t)value << 1); else - zigzagged = (pb_uint64_t)value << 1; + zigzagged = (uint64_t)value << 1; return pb_encode_varint(stream, zigzagged); } bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) { - uint32_t val = *(const uint32_t*)value; - pb_byte_t bytes[4]; - bytes[0] = (pb_byte_t)(val & 0xFF); - bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); - bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); - bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); - return pb_write(stream, bytes, 4); + #ifdef __BIG_ENDIAN__ + const uint8_t *bytes = value; + uint8_t lebytes[4]; + lebytes[0] = bytes[3]; + lebytes[1] = bytes[2]; + lebytes[2] = bytes[1]; + lebytes[3] = bytes[0]; + return pb_write(stream, lebytes, 4); + #else + return pb_write(stream, (const uint8_t*)value, 4); + #endif } -#ifndef PB_WITHOUT_64BIT bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) { - uint64_t val = *(const uint64_t*)value; - pb_byte_t bytes[8]; - bytes[0] = (pb_byte_t)(val & 0xFF); - bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); - bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); - bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); - bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); - bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); - bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); - bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); - return pb_write(stream, bytes, 8); + #ifdef __BIG_ENDIAN__ + const uint8_t *bytes = value; + uint8_t lebytes[8]; + lebytes[0] = bytes[7]; + lebytes[1] = bytes[6]; + lebytes[2] = bytes[5]; + lebytes[3] = bytes[4]; + lebytes[4] = bytes[3]; + lebytes[5] = bytes[2]; + lebytes[6] = bytes[1]; + lebytes[7] = bytes[0]; + return pb_write(stream, lebytes, 8); + #else + return pb_write(stream, (const uint8_t*)value, 8); + #endif } -#endif bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) { - pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + uint64_t tag = ((uint64_t)field_number << 3) | wiretype; return pb_encode_varint(stream, tag); } @@ -660,7 +484,6 @@ bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t case PB_LTYPE_BYTES: case PB_LTYPE_STRING: case PB_LTYPE_SUBMESSAGE: - case PB_LTYPE_FIXED_LENGTH_BYTES: wiretype = PB_WT_STRING; break; @@ -671,9 +494,9 @@ bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t return pb_encode_tag(stream, wiretype, field->tag); } -bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +bool checkreturn pb_encode_string(pb_ostream_t *stream, const uint8_t *buffer, size_t size) { - if (!pb_encode_varint(stream, (pb_uint64_t)size)) + if (!pb_encode_varint(stream, (uint64_t)size)) return false; return pb_write(stream, buffer, size); @@ -696,7 +519,7 @@ bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fie size = substream.bytes_written; - if (!pb_encode_varint(stream, (pb_uint64_t)size)) + if (!pb_encode_varint(stream, (uint64_t)size)) return false; if (stream->callback == NULL) @@ -733,89 +556,69 @@ bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fie static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - pb_int64_t value = 0; - - if (field->data_size == sizeof(int_least8_t)) - value = *(const int_least8_t*)src; - else if (field->data_size == sizeof(int_least16_t)) - value = *(const int_least16_t*)src; - else if (field->data_size == sizeof(int32_t)) - value = *(const int32_t*)src; - else if (field->data_size == sizeof(pb_int64_t)) - value = *(const pb_int64_t*)src; - else - PB_RETURN_ERROR(stream, "invalid data_size"); + int64_t value = 0; -#ifdef PB_WITHOUT_64BIT - if (value < 0) - return pb_encode_negative_varint(stream, (pb_uint64_t)value); - else -#endif - return pb_encode_varint(stream, (pb_uint64_t)value); + /* Cases 1 and 2 are for compilers that have smaller types for bool + * or enums. */ + switch (field->data_size) + { + case 1: value = *(const int8_t*)src; break; + case 2: value = *(const int16_t*)src; break; + case 4: value = *(const int32_t*)src; break; + case 8: value = *(const int64_t*)src; break; + default: PB_RETURN_ERROR(stream, "invalid data_size"); + } + + return pb_encode_varint(stream, (uint64_t)value); } static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - pb_uint64_t value = 0; - - if (field->data_size == sizeof(uint_least8_t)) - value = *(const uint_least8_t*)src; - else if (field->data_size == sizeof(uint_least16_t)) - value = *(const uint_least16_t*)src; - else if (field->data_size == sizeof(uint32_t)) - value = *(const uint32_t*)src; - else if (field->data_size == sizeof(pb_uint64_t)) - value = *(const pb_uint64_t*)src; - else - PB_RETURN_ERROR(stream, "invalid data_size"); + uint64_t value = 0; + + switch (field->data_size) + { + case 4: value = *(const uint32_t*)src; break; + case 8: value = *(const uint64_t*)src; break; + default: PB_RETURN_ERROR(stream, "invalid data_size"); + } return pb_encode_varint(stream, value); } static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - pb_int64_t value = 0; - - if (field->data_size == sizeof(int_least8_t)) - value = *(const int_least8_t*)src; - else if (field->data_size == sizeof(int_least16_t)) - value = *(const int_least16_t*)src; - else if (field->data_size == sizeof(int32_t)) - value = *(const int32_t*)src; - else if (field->data_size == sizeof(pb_int64_t)) - value = *(const pb_int64_t*)src; - else - PB_RETURN_ERROR(stream, "invalid data_size"); + int64_t value = 0; + + switch (field->data_size) + { + case 4: value = *(const int32_t*)src; break; + case 8: value = *(const int64_t*)src; break; + default: PB_RETURN_ERROR(stream, "invalid data_size"); + } return pb_encode_svarint(stream, value); } static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - PB_UNUSED(field); -#ifndef PB_WITHOUT_64BIT + UNUSED(field); return pb_encode_fixed64(stream, src); -#else - PB_UNUSED(src); - PB_RETURN_ERROR(stream, "no 64bit support"); -#endif } static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - PB_UNUSED(field); + UNUSED(field); return pb_encode_fixed32(stream, src); } static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - const pb_bytes_array_t *bytes = NULL; - - bytes = (const pb_bytes_array_t*)src; + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src; if (src == NULL) { - /* Treat null pointer as an empty bytes field */ + /* Threat null pointer as an empty bytes field */ return pb_encode_string(stream, NULL, 0); } @@ -830,6 +633,7 @@ static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *fie static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) { + /* strnlen() is not always available, so just use a loop */ size_t size = 0; size_t max_size = field->data_size; const char *p = (const char*)src; @@ -839,11 +643,10 @@ static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *fi if (src == NULL) { - size = 0; /* Treat null pointer as an empty string */ + size = 0; /* Threat null pointer as an empty string */ } else { - /* strnlen() is not always available, so just use a loop */ while (size < max_size && *p != '\0') { size++; @@ -851,7 +654,7 @@ static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *fi } } - return pb_encode_string(stream, (const pb_byte_t*)src, size); + return pb_encode_string(stream, (const uint8_t*)src, size); } static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) @@ -862,8 +665,3 @@ static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); } -static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); -} - |