17ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* pb_encode.c -- encode a protobuf using minimal resources 27ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * 37ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * 2011 Petteri Aimonen <jpa@kapsi.fi> 47ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */ 57ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 67ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "pb.h" 77ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "pb_encode.h" 87ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 97ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Use the GCC warn_unused_result attribute to check that all return values 107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * are propagated correctly. On other compilers and gcc before 3.4.0 just 117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * ignore the annotation. 127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */ 137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) 147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #define checkreturn 157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#else 167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #define checkreturn __attribute__((warn_unused_result)) 177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/************************************** 207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Declarations internal to this file * 217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen **************************************/ 227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohentypedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; 237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count); 257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); 267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); 277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); 287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); 297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); 307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); 317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); 327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); 337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); 347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); 357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); 367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); 377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* --- Function pointers to field encoders --- 397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Order in the array must match pb_action_t LTYPE numbering. 407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */ 417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { 427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_varint, 437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_uvarint, 447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_svarint, 457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_fixed32, 467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_fixed64, 477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_bytes, 497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_string, 507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen &pb_enc_submessage, 517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen NULL /* extensions */ 527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen}; 537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/******************************* 557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * pb_ostream_t implementation * 567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen *******************************/ 577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count) 597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t *dest = (uint8_t*)stream->state; 617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream->state = dest + count; 627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen while (count--) 647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen *dest++ = *buf++; 657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenpb_ostream_t pb_ostream_from_buffer(uint8_t *buf, size_t bufsize) 707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_ostream_t stream; 727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifdef PB_BUFFER_ONLY 737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream.callback = (void*)1; /* Just a marker value */ 747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#else 757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream.callback = &buf_write; 767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream.state = buf; 787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream.max_size = bufsize; 797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream.bytes_written = 0; 807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifndef PB_NO_ERRMSG 817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream.errmsg = NULL; 827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return stream; 847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count) 877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (stream->callback != NULL) 897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (stream->bytes_written + count > stream->max_size) 917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "stream full"); 927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifdef PB_BUFFER_ONLY 947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!buf_write(stream, buf, count)) 957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "io error"); 967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#else 977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!stream->callback(stream, buf, count)) 987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "io error"); 997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 1007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream->bytes_written += count; 1037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 1047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 1057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/************************* 1077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Encode a single field * 1087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen *************************/ 1097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Encode a static array. Handles the size calculations and possible packing. */ 1117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, 1127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const void *pData, size_t count, pb_encoder_t func) 1137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 1147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t i; 1157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const void *p; 1167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t size; 1177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (count == 0) 1197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 1207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) 1227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "array max size exceeded"); 1237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* We always pack arrays if the datatype allows it. */ 1257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) 1267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) 1287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Determine the total size of packed array. */ 1317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) 1327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size = 4 * count; 1347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) 1367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size = 8 * count; 1387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 1407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_ostream_t sizestream = PB_OSTREAM_SIZING; 1427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p = pData; 1437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen for (i = 0; i < count; i++) 1447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!func(&sizestream, field, p)) 1467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p = (const char*)p + field->data_size; 1487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size = sizestream.bytes_written; 1507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_varint(stream, (uint64_t)size)) 1537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (stream->callback == NULL) 1567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, NULL, size); /* Just sizing.. */ 1577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Write the data */ 1597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p = pData; 1607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen for (i = 0; i < count; i++) 1617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!func(stream, field, p)) 1637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p = (const char*)p + field->data_size; 1657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 1687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p = pData; 1707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen for (i = 0; i < count; i++) 1717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_tag_for_field(stream, field)) 1737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Normally the data is stored directly in the array entries, but 1767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * for pointer-type string and bytes fields, the array entries are 1777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * actually pointers themselves also. So we have to dereference once 1787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * more to get to the actual data. */ 1797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && 1807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen (PB_LTYPE(field->type) == PB_LTYPE_STRING || 1817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_LTYPE(field->type) == PB_LTYPE_BYTES)) 1827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!func(stream, field, *(const void* const*)p)) 1847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 1877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!func(stream, field, p)) 1897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 1907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p = (const char*)p + field->data_size; 1927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 1967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 1977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Encode a field with static or pointer allocation, i.e. one whose data 1997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * is available to the encoder directly. */ 2007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_basic_field(pb_ostream_t *stream, 2017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_field_t *field, const void *pData) 2027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 2037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_encoder_t func; 2047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const void *pSize; 2057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen bool implicit_has = true; 2067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen func = PB_ENCODERS[PB_LTYPE(field->type)]; 2087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (field->size_offset) 2107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pSize = (const char*)pData + field->size_offset; 2117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 2127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pSize = &implicit_has; 2137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) 2157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 2167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* pData is a pointer to the field, which contains pointer to 2177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * the data. If the 2nd pointer is NULL, it is interpreted as if 2187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * the has_field was false. 2197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */ 2207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pData = *(const void* const*)pData; 2227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen implicit_has = (pData != NULL); 2237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 2247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen switch (PB_HTYPE(field->type)) 2267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 2277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_HTYPE_REQUIRED: 2287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pData) 2297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "missing required field"); 2307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_tag_for_field(stream, field)) 2317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 2327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!func(stream, field, pData)) 2337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 2347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 2357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_HTYPE_OPTIONAL: 2377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (*(const bool*)pSize) 2387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 2397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_tag_for_field(stream, field)) 2407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 2417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!func(stream, field, pData)) 2437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 2447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 2457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 2467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_HTYPE_REPEATED: 2487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!encode_array(stream, field, pData, *(const size_t*)pSize, func)) 2497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 2507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 2517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen default: 2537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "invalid field type"); 2547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 2557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 2577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 2587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Encode a field with callback semantics. This means that a user function is 2607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * called to provide and encode the actual data. */ 2617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_callback_field(pb_ostream_t *stream, 2627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_field_t *field, const void *pData) 2637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 2647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_callback_t *callback = (const pb_callback_t*)pData; 2657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifdef PB_OLD_CALLBACK_STYLE 2677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const void *arg = callback->arg; 2687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#else 2697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen void * const *arg = &(callback->arg); 2707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 2717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (callback->funcs.encode != NULL) 2737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 2747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!callback->funcs.encode(stream, field, arg)) 2757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "callback error"); 2767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 2777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 2787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 2797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Encode a single field of any callback or static type. */ 2817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_field(pb_ostream_t *stream, 2827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_field_t *field, const void *pData) 2837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 2847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen switch (PB_ATYPE(field->type)) 2857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 2867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_ATYPE_STATIC: 2877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_ATYPE_POINTER: 2887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return encode_basic_field(stream, field, pData); 2897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_ATYPE_CALLBACK: 2917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return encode_callback_field(stream, field, pData); 2927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen default: 2947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "invalid field type"); 2957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 2967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 2977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 2987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Default handler for extension fields. Expects to have a pb_field_t 2997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * pointer in the extension->type->arg field. */ 3007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn default_extension_encoder(pb_ostream_t *stream, 3017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_extension_t *extension) 3027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 3037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_field_t *field = (const pb_field_t*)extension->type->arg; 3047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return encode_field(stream, field, extension->dest); 3057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 3067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Walk through all the registered extensions and give them a chance 3087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * to encode themselves. */ 3097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn encode_extension_field(pb_ostream_t *stream, 3107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_field_t *field, const void *pData) 3117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 3127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_extension_t *extension = *(const pb_extension_t* const *)pData; 3137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen UNUSED(field); 3147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen while (extension) 3167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 3177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen bool status; 3187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (extension->type->encode) 3197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen status = extension->type->encode(stream, extension); 3207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 3217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen status = default_extension_encoder(stream, extension); 3227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!status) 3247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 3257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen extension = extension->next; 3277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 3287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 3307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 3317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/********************* 3337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Encode all fields * 3347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen *********************/ 3357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) 3377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 3387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_field_t *field = fields; 3397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const void *pData = src_struct; 3407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t prev_size = 0; 3417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen while (field->tag != 0) 3437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 3447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pData = (const char*)pData + prev_size + field->data_offset; 3457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) 3467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen prev_size = sizeof(const void*); 3477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 3487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen prev_size = field->data_size; 3497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Special case for static arrays */ 3517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && 3527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_HTYPE(field->type) == PB_HTYPE_REPEATED) 3537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 3547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen prev_size *= field->array_size; 3557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 3567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_LTYPE(field->type) == PB_LTYPE_EXTENSION) 3587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 3597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Special case for the extension field placeholder */ 3607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!encode_extension_field(stream, field, pData)) 3617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 3627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 3637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 3647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 3657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Regular field */ 3667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!encode_field(stream, field, pData)) 3677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 3687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 3697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen field++; 3717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 3727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 3747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 3757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) 3777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 3787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_submessage(stream, fields, src_struct); 3797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 3807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) 3827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 3837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_ostream_t stream = PB_OSTREAM_SIZING; 3847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode(&stream, fields, src_struct)) 3867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 3877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen *size = stream.bytes_written; 3897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 3907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 3917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 3927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/******************** 3937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * Helper functions * 3947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen ********************/ 3957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value) 3967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 3977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t buffer[10]; 3987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t i = 0; 3997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (value == 0) 4017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, (uint8_t*)&value, 1); 4027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen while (value) 4047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 4057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen buffer[i] = (uint8_t)((value & 0x7F) | 0x80); 4067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen value >>= 7; 4077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen i++; 4087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 4097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ 4107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, buffer, i); 4127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 4137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value) 4157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 4167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint64_t zigzagged; 4177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (value < 0) 4187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen zigzagged = ~((uint64_t)value << 1); 4197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 4207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen zigzagged = (uint64_t)value << 1; 4217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_varint(stream, zigzagged); 4237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 4247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) 4267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 4277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #ifdef __BIG_ENDIAN__ 4287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const uint8_t *bytes = value; 4297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t lebytes[4]; 4307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[0] = bytes[3]; 4317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[1] = bytes[2]; 4327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[2] = bytes[1]; 4337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[3] = bytes[0]; 4347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, lebytes, 4); 4357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #else 4367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, (const uint8_t*)value, 4); 4377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #endif 4387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 4397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) 4417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 4427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #ifdef __BIG_ENDIAN__ 4437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const uint8_t *bytes = value; 4447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t lebytes[8]; 4457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[0] = bytes[7]; 4467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[1] = bytes[6]; 4477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[2] = bytes[5]; 4487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[3] = bytes[4]; 4497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[4] = bytes[3]; 4507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[5] = bytes[2]; 4517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[6] = bytes[1]; 4527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen lebytes[7] = bytes[0]; 4537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, lebytes, 8); 4547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #else 4557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, (const uint8_t*)value, 8); 4567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen #endif 4577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 4587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) 4607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 4617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint64_t tag = ((uint64_t)field_number << 3) | wiretype; 4627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_varint(stream, tag); 4637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 4647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) 4667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 4677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_wire_type_t wiretype; 4687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen switch (PB_LTYPE(field->type)) 4697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 4707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_VARINT: 4717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_UVARINT: 4727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_SVARINT: 4737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen wiretype = PB_WT_VARINT; 4747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 4757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_FIXED32: 4777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen wiretype = PB_WT_32BIT; 4787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 4797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_FIXED64: 4817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen wiretype = PB_WT_64BIT; 4827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 4837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_BYTES: 4857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_STRING: 4867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case PB_LTYPE_SUBMESSAGE: 4877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen wiretype = PB_WT_STRING; 4887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen break; 4897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen default: 4917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "invalid field type"); 4927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 4937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_tag(stream, wiretype, field->tag); 4957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 4967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 4977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_string(pb_ostream_t *stream, const uint8_t *buffer, size_t size) 4987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 4997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_varint(stream, (uint64_t)size)) 5007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 5017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, buffer, size); 5037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 5047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) 5067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 5077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* First calculate the message size using a non-writing substream. */ 5087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_ostream_t substream = PB_OSTREAM_SIZING; 5097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t size; 5107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen bool status; 5117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode(&substream, fields, src_struct)) 5137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 5147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifndef PB_NO_ERRMSG 5157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream->errmsg = substream.errmsg; 5167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 5177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 5187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 5197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size = substream.bytes_written; 5217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode_varint(stream, (uint64_t)size)) 5237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 5247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (stream->callback == NULL) 5267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_write(stream, NULL, size); /* Just sizing */ 5277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (stream->bytes_written + size > stream->max_size) 5297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "stream full"); 5307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Use a substream to verify that a callback doesn't write more than 5327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * what it did the first time. */ 5337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen substream.callback = stream->callback; 5347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen substream.state = stream->state; 5357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen substream.max_size = size; 5367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen substream.bytes_written = 0; 5377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifndef PB_NO_ERRMSG 5387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen substream.errmsg = NULL; 5397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 5407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen status = pb_encode(&substream, fields, src_struct); 5427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream->bytes_written += substream.bytes_written; 5447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream->state = substream.state; 5457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#ifndef PB_NO_ERRMSG 5467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen stream->errmsg = substream.errmsg; 5477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#endif 5487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (substream.bytes_written != size) 5507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "submsg size changed"); 5517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return status; 5537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 5547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* Field encoders */ 5567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) 5587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 5597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen int64_t value = 0; 5607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Cases 1 and 2 are for compilers that have smaller types for bool 5627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * or enums. */ 5637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen switch (field->data_size) 5647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 5657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 1: value = *(const int8_t*)src; break; 5667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 2: value = *(const int16_t*)src; break; 5677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 4: value = *(const int32_t*)src; break; 5687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 8: value = *(const int64_t*)src; break; 5697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen default: PB_RETURN_ERROR(stream, "invalid data_size"); 5707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 5717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_varint(stream, (uint64_t)value); 5737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 5747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) 5767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 5777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint64_t value = 0; 5787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen switch (field->data_size) 5807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 5817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 4: value = *(const uint32_t*)src; break; 5827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 8: value = *(const uint64_t*)src; break; 5837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen default: PB_RETURN_ERROR(stream, "invalid data_size"); 5847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 5857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_varint(stream, value); 5877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 5887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) 5907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 5917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen int64_t value = 0; 5927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 5937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen switch (field->data_size) 5947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 5957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 4: value = *(const int32_t*)src; break; 5967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen case 8: value = *(const int64_t*)src; break; 5977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen default: PB_RETURN_ERROR(stream, "invalid data_size"); 5987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 5997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_svarint(stream, value); 6017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 6027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) 6047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 6057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen UNUSED(field); 6067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_fixed64(stream, src); 6077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 6087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) 6107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 6117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen UNUSED(field); 6127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_fixed32(stream, src); 6137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 6147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) 6167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 6177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src; 6187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (src == NULL) 6207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 6217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* Threat null pointer as an empty bytes field */ 6227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_string(stream, NULL, 0); 6237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 6247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && 6267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) 6277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 6287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "bytes size exceeded"); 6297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 6307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_string(stream, bytes->bytes, bytes->size); 6327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 6337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) 6357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 6367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* strnlen() is not always available, so just use a loop */ 6377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t size = 0; 6387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size_t max_size = field->data_size; 6397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen const char *p = (const char*)src; 6407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) 6427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen max_size = (size_t)-1; 6437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (src == NULL) 6457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 6467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size = 0; /* Threat null pointer as an empty string */ 6477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 6487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 6497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 6507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen while (size < max_size && *p != '\0') 6517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 6527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen size++; 6537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen p++; 6547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 6557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 6567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_string(stream, (const uint8_t*)src, size); 6587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 6597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenstatic bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) 6617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 6627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (field->ptr == NULL) 6637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen PB_RETURN_ERROR(stream, "invalid field descriptor"); 6647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 6657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); 6667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 6677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 668