+static size_t
+get_packed_payload_length (const ProtobufCFieldDescriptor *field,
+ unsigned count,
+ const void *array)
+{
+ unsigned rv = 0;
+ unsigned i;
+ switch (field->type)
+ {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ return count * 4;
+
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return count * 8;
+
+ case PROTOBUF_C_TYPE_INT32:
+ {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += int32_size (arr[i]);
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_SINT32:
+ {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += sint32_size (arr[i]);
+ }
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_UINT32:
+ {
+ const uint32_t *arr = (const uint32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += uint32_size (arr[i]);
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_SINT64:
+ {
+ const int64_t *arr = (const int64_t *) array;
+ for (i = 0; i < count; i++)
+ rv += sint64_size (arr[i]);
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ {
+ const uint64_t *arr = (const uint64_t *) array;
+ for (i = 0; i < count; i++)
+ rv += uint64_size (arr[i]);
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ return count;
+ default:
+ assert (0);
+ }
+ return rv;
+}
+static size_t
+pack_buffer_packed_payload (const ProtobufCFieldDescriptor *field,
+ unsigned count,
+ const void *array,
+ ProtobufCBuffer *buffer)
+{
+ uint8_t scratch[16];
+ size_t rv = 0;
+ unsigned i;
+ switch (field->type)
+ {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+#if IS_LITTLE_ENDIAN
+ rv = count * 4;
+ goto no_packing_needed;
+#else
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = fixed32_pack (((uint32_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+#endif
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+#if IS_LITTLE_ENDIAN
+ rv = count * 8;
+ goto no_packing_needed;
+#else
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = fixed64_pack (((uint64_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_INT32:
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = int32_pack (((int32_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_SINT32:
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = sint32_pack (((int32_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_UINT32:
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = uint32_pack (((uint32_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_SINT64:
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = sint64_pack (((int64_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = uint64_pack (((uint64_t*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ for (i = 0; i < count; i++)
+ {
+ unsigned len = boolean_pack (((protobuf_c_boolean*)array)[i], scratch);
+ buffer->append (buffer, len, scratch);
+ rv += len;
+ }
+ return count;
+ default:
+ assert(0);
+ }
+ return rv;
+
+no_packing_needed:
+ buffer->append (buffer, rv, array);
+ return rv;
+}
+