1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32//  Based on original Protocol Buffers design by
33//  Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <stack>
36#include <string>
37#include <vector>
38
39#include <google/protobuf/wire_format.h>
40
41#include <google/protobuf/stubs/common.h>
42#include <google/protobuf/descriptor.h>
43#include <google/protobuf/wire_format_lite_inl.h>
44#include <google/protobuf/descriptor.pb.h>
45#include <google/protobuf/io/coded_stream.h>
46#include <google/protobuf/io/zero_copy_stream.h>
47#include <google/protobuf/io/zero_copy_stream_impl.h>
48#include <google/protobuf/unknown_field_set.h>
49
50
51
52namespace google {
53namespace protobuf {
54namespace internal {
55
56namespace {
57
58// This function turns out to be convenient when using some macros later.
59inline int GetEnumNumber(const EnumValueDescriptor* descriptor) {
60  return descriptor->number();
61}
62
63}  // anonymous namespace
64
65bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input,
66                                      Message* message) {
67  const Descriptor* descriptor = message->GetDescriptor();
68  const Reflection* message_reflection = message->GetReflection();
69
70  while(true) {
71    uint32 tag = input->ReadTag();
72    if (tag == 0) {
73      // End of input.  This is a valid place to end, so return true.
74      return true;
75    }
76
77    if (WireFormatLite::GetTagWireType(tag) ==
78        WireFormatLite::WIRETYPE_END_GROUP) {
79      // Must be the end of the message.
80      return true;
81    }
82
83    const FieldDescriptor* field = NULL;
84
85    if (descriptor != NULL) {
86      int field_number = WireFormatLite::GetTagFieldNumber(tag);
87      field = descriptor->FindFieldByNumber(field_number);
88
89      // If that failed, check if the field is an extension.
90      if (field == NULL && descriptor->IsExtensionNumber(field_number)) {
91        if (input->GetExtensionPool() == NULL) {
92          field = message_reflection->FindKnownExtensionByNumber(field_number);
93        } else {
94          field = input->GetExtensionPool()
95                       ->FindExtensionByNumber(descriptor, field_number);
96        }
97      }
98
99      // If that failed, but we're a MessageSet, and this is the tag for a
100      // MessageSet item, then parse that.
101      if (field == NULL &&
102          descriptor->options().message_set_wire_format() &&
103          tag == WireFormatLite::kMessageSetItemStartTag) {
104        if (!ParseAndMergeMessageSetItem(input, message)) {
105          return false;
106        }
107        continue;  // Skip ParseAndMergeField(); already taken care of.
108      }
109    }
110
111    if (!ParseAndMergeField(tag, field, message, input)) {
112      return false;
113    }
114  }
115}
116
117bool WireFormat::ParseAndMergeField(
118    uint32 tag,
119    const FieldDescriptor* field,        // May be NULL for unknown
120    Message* message,
121    io::CodedInputStream* input) {
122  const Reflection* message_reflection = message->GetReflection();
123
124  enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
125
126  if (field == NULL) {
127    value_format = UNKNOWN;
128  } else if (WireFormatLite::GetTagWireType(tag) ==
129             WireTypeForFieldType(field->type())) {
130    value_format = NORMAL_FORMAT;
131  } else if (field->is_packable() &&
132             WireFormatLite::GetTagWireType(tag) ==
133             WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
134    value_format = PACKED_FORMAT;
135  } else {
136    // We don't recognize this field. Either the field number is unknown
137    // or the wire type doesn't match. Put it in our unknown field set.
138    value_format = UNKNOWN;
139  }
140
141  if (value_format == UNKNOWN) {
142    return WireFormatLite::SkipField(
143        input, tag, message_reflection->MutableUnknownFields(message));
144  } else if (value_format == PACKED_FORMAT) {
145    uint32 length;
146    if (!input->ReadVarint32(&length)) return false;
147    io::CodedInputStream::Limit limit = input->PushLimit(length);
148
149    switch (field->type()) {
150#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD)                      \
151      case FieldDescriptor::TYPE_##TYPE: {                                     \
152        while (input->BytesUntilLimit() > 0) {                                 \
153          CPPTYPE value;                                                       \
154          if (!WireFormatLite::ReadPrimitive<                                  \
155                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value))          \
156            return false;                                                      \
157          message_reflection->Add##CPPTYPE_METHOD(message, field, value);      \
158        }                                                                      \
159        break;                                                                 \
160      }
161
162      HANDLE_PACKED_TYPE( INT32,  int32,  Int32)
163      HANDLE_PACKED_TYPE( INT64,  int64,  Int64)
164      HANDLE_PACKED_TYPE(SINT32,  int32,  Int32)
165      HANDLE_PACKED_TYPE(SINT64,  int64,  Int64)
166      HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
167      HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
168
169      HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32)
170      HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64)
171      HANDLE_PACKED_TYPE(SFIXED32,  int32,  Int32)
172      HANDLE_PACKED_TYPE(SFIXED64,  int64,  Int64)
173
174      HANDLE_PACKED_TYPE(FLOAT , float , Float )
175      HANDLE_PACKED_TYPE(DOUBLE, double, Double)
176
177      HANDLE_PACKED_TYPE(BOOL, bool, Bool)
178#undef HANDLE_PACKED_TYPE
179
180      case FieldDescriptor::TYPE_ENUM: {
181        while (input->BytesUntilLimit() > 0) {
182          int value;
183          if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
184                  input, &value)) return false;
185          const EnumValueDescriptor* enum_value =
186              field->enum_type()->FindValueByNumber(value);
187          if (enum_value != NULL) {
188            message_reflection->AddEnum(message, field, enum_value);
189          }
190        }
191
192        break;
193      }
194
195      case FieldDescriptor::TYPE_STRING:
196      case FieldDescriptor::TYPE_GROUP:
197      case FieldDescriptor::TYPE_MESSAGE:
198      case FieldDescriptor::TYPE_BYTES:
199        // Can't have packed fields of these types: these should be caught by
200        // the protocol compiler.
201        return false;
202        break;
203    }
204
205    input->PopLimit(limit);
206  } else {
207    // Non-packed value (value_format == NORMAL_FORMAT)
208    switch (field->type()) {
209#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD)                            \
210      case FieldDescriptor::TYPE_##TYPE: {                                    \
211        CPPTYPE value;                                                        \
212        if (!WireFormatLite::ReadPrimitive<                                   \
213                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value))         \
214          return false;                                                       \
215        if (field->is_repeated()) {                                           \
216          message_reflection->Add##CPPTYPE_METHOD(message, field, value);     \
217        } else {                                                              \
218          message_reflection->Set##CPPTYPE_METHOD(message, field, value);     \
219        }                                                                     \
220        break;                                                                \
221      }
222
223      HANDLE_TYPE( INT32,  int32,  Int32)
224      HANDLE_TYPE( INT64,  int64,  Int64)
225      HANDLE_TYPE(SINT32,  int32,  Int32)
226      HANDLE_TYPE(SINT64,  int64,  Int64)
227      HANDLE_TYPE(UINT32, uint32, UInt32)
228      HANDLE_TYPE(UINT64, uint64, UInt64)
229
230      HANDLE_TYPE( FIXED32, uint32, UInt32)
231      HANDLE_TYPE( FIXED64, uint64, UInt64)
232      HANDLE_TYPE(SFIXED32,  int32,  Int32)
233      HANDLE_TYPE(SFIXED64,  int64,  Int64)
234
235      HANDLE_TYPE(FLOAT , float , Float )
236      HANDLE_TYPE(DOUBLE, double, Double)
237
238      HANDLE_TYPE(BOOL, bool, Bool)
239#undef HANDLE_TYPE
240
241      case FieldDescriptor::TYPE_ENUM: {
242        int value;
243        if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
244                input, &value)) return false;
245        const EnumValueDescriptor* enum_value =
246          field->enum_type()->FindValueByNumber(value);
247        if (enum_value != NULL) {
248          if (field->is_repeated()) {
249            message_reflection->AddEnum(message, field, enum_value);
250          } else {
251            message_reflection->SetEnum(message, field, enum_value);
252          }
253        } else {
254          // The enum value is not one of the known values.  Add it to the
255          // UnknownFieldSet.
256          int64 sign_extended_value = static_cast<int64>(value);
257          message_reflection->MutableUnknownFields(message)
258                            ->AddVarint(WireFormatLite::GetTagFieldNumber(tag),
259                                        sign_extended_value);
260        }
261        break;
262      }
263
264      // Handle strings separately so that we can optimize the ctype=CORD case.
265      case FieldDescriptor::TYPE_STRING: {
266        string value;
267        if (!WireFormatLite::ReadString(input, &value)) return false;
268        VerifyUTF8String(value.data(), value.length(), PARSE);
269        if (field->is_repeated()) {
270          message_reflection->AddString(message, field, value);
271        } else {
272          message_reflection->SetString(message, field, value);
273        }
274        break;
275      }
276
277      case FieldDescriptor::TYPE_BYTES: {
278        string value;
279        if (!WireFormatLite::ReadBytes(input, &value)) return false;
280        if (field->is_repeated()) {
281          message_reflection->AddString(message, field, value);
282        } else {
283          message_reflection->SetString(message, field, value);
284        }
285        break;
286      }
287
288      case FieldDescriptor::TYPE_GROUP: {
289        Message* sub_message;
290        if (field->is_repeated()) {
291          sub_message = message_reflection->AddMessage(
292              message, field, input->GetExtensionFactory());
293        } else {
294          sub_message = message_reflection->MutableMessage(
295              message, field, input->GetExtensionFactory());
296        }
297
298        if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
299                                       input, sub_message))
300          return false;
301        break;
302      }
303
304      case FieldDescriptor::TYPE_MESSAGE: {
305        Message* sub_message;
306        if (field->is_repeated()) {
307          sub_message = message_reflection->AddMessage(
308              message, field, input->GetExtensionFactory());
309        } else {
310          sub_message = message_reflection->MutableMessage(
311              message, field, input->GetExtensionFactory());
312        }
313
314        if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
315        break;
316      }
317    }
318  }
319
320  return true;
321}
322
323bool WireFormat::ParseAndMergeMessageSetItem(
324    io::CodedInputStream* input,
325    Message* message) {
326  const Reflection* message_reflection = message->GetReflection();
327
328  // This method parses a group which should contain two fields:
329  //   required int32 type_id = 2;
330  //   required data message = 3;
331
332  // Once we see a type_id, we'll construct a fake tag for this extension
333  // which is the tag it would have had under the proto2 extensions wire
334  // format.
335  uint32 fake_tag = 0;
336
337  // Once we see a type_id, we'll look up the FieldDescriptor for the
338  // extension.
339  const FieldDescriptor* field = NULL;
340
341  // If we see message data before the type_id, we'll append it to this so
342  // we can parse it later.
343  string message_data;
344
345  while (true) {
346    uint32 tag = input->ReadTag();
347    if (tag == 0) return false;
348
349    switch (tag) {
350      case WireFormatLite::kMessageSetTypeIdTag: {
351        uint32 type_id;
352        if (!input->ReadVarint32(&type_id)) return false;
353        fake_tag = WireFormatLite::MakeTag(
354            type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
355        field = message_reflection->FindKnownExtensionByNumber(type_id);
356
357        if (!message_data.empty()) {
358          // We saw some message data before the type_id.  Have to parse it
359          // now.
360          io::ArrayInputStream raw_input(message_data.data(),
361                                         message_data.size());
362          io::CodedInputStream sub_input(&raw_input);
363          if (!ParseAndMergeField(fake_tag, field, message,
364                                  &sub_input)) {
365            return false;
366          }
367          message_data.clear();
368        }
369
370        break;
371      }
372
373      case WireFormatLite::kMessageSetMessageTag: {
374        if (fake_tag == 0) {
375          // We haven't seen a type_id yet.  Append this data to message_data.
376          string temp;
377          uint32 length;
378          if (!input->ReadVarint32(&length)) return false;
379          if (!input->ReadString(&temp, length)) return false;
380          io::StringOutputStream output_stream(&message_data);
381          io::CodedOutputStream coded_output(&output_stream);
382          coded_output.WriteVarint32(length);
383          coded_output.WriteString(temp);
384        } else {
385          // Already saw type_id, so we can parse this directly.
386          if (!ParseAndMergeField(fake_tag, field, message, input)) {
387            return false;
388          }
389        }
390
391        break;
392      }
393
394      case WireFormatLite::kMessageSetItemEndTag: {
395        return true;
396      }
397
398      default: {
399        if (!WireFormatLite::SkipField(input, tag, NULL)) return false;
400      }
401    }
402  }
403}
404
405// ===================================================================
406
407void WireFormat::SerializeWithCachedSizes(
408    const Message& message,
409    int size, io::CodedOutputStream* output) {
410  const Descriptor* descriptor = message.GetDescriptor();
411  const Reflection* message_reflection = message.GetReflection();
412  int expected_endpoint = output->ByteCount() + size;
413
414  vector<const FieldDescriptor*> fields;
415  message_reflection->ListFields(message, &fields);
416  for (int i = 0; i < fields.size(); i++) {
417    SerializeFieldWithCachedSizes(fields[i], message, output);
418  }
419
420  if (descriptor->options().message_set_wire_format()) {
421    WireFormatLite::SerializeUnknownMessageSetItems(
422        message_reflection->GetUnknownFields(message), output);
423  } else {
424    WireFormatLite::SerializeUnknownFields(
425        message_reflection->GetUnknownFields(message), output);
426  }
427
428  GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint)
429    << ": Protocol message serialized to a size different from what was "
430       "originally expected.  Perhaps it was modified by another thread "
431       "during serialization?";
432}
433
434void WireFormat::SerializeFieldWithCachedSizes(
435    const FieldDescriptor* field,
436    const Message& message,
437    io::CodedOutputStream* output) {
438  const Reflection* message_reflection = message.GetReflection();
439
440  if (field->is_extension() &&
441      field->containing_type()->options().message_set_wire_format() &&
442      field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
443      !field->is_repeated()) {
444    SerializeMessageSetItemWithCachedSizes(field, message, output);
445    return;
446  }
447
448  int count = 0;
449
450  if (field->is_repeated()) {
451    count = message_reflection->FieldSize(message, field);
452  } else if (message_reflection->HasField(message, field)) {
453    count = 1;
454  }
455
456  const bool is_packed = field->options().packed();
457  if (is_packed && count > 0) {
458    WireFormatLite::WriteTag(field->number(),
459        WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
460    const int data_size = FieldDataOnlyByteSize(field, message);
461    output->WriteVarint32(data_size);
462  }
463
464  for (int j = 0; j < count; j++) {
465    switch (field->type()) {
466#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD)      \
467      case FieldDescriptor::TYPE_##TYPE: {                                     \
468        const CPPTYPE value = field->is_repeated() ?                           \
469                              message_reflection->GetRepeated##CPPTYPE_METHOD( \
470                                message, field, j) :                           \
471                              message_reflection->Get##CPPTYPE_METHOD(         \
472                                message, field);                               \
473        if (is_packed) {                                                       \
474          WireFormatLite::Write##TYPE_METHOD##NoTag(value, output);            \
475        } else {                                                               \
476          WireFormatLite::Write##TYPE_METHOD(field->number(), value, output);  \
477        }                                                                      \
478        break;                                                                 \
479      }
480
481      HANDLE_PRIMITIVE_TYPE( INT32,  int32,  Int32,  Int32)
482      HANDLE_PRIMITIVE_TYPE( INT64,  int64,  Int64,  Int64)
483      HANDLE_PRIMITIVE_TYPE(SINT32,  int32, SInt32,  Int32)
484      HANDLE_PRIMITIVE_TYPE(SINT64,  int64, SInt64,  Int64)
485      HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32)
486      HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64)
487
488      HANDLE_PRIMITIVE_TYPE( FIXED32, uint32,  Fixed32, UInt32)
489      HANDLE_PRIMITIVE_TYPE( FIXED64, uint64,  Fixed64, UInt64)
490      HANDLE_PRIMITIVE_TYPE(SFIXED32,  int32, SFixed32,  Int32)
491      HANDLE_PRIMITIVE_TYPE(SFIXED64,  int64, SFixed64,  Int64)
492
493      HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float )
494      HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double)
495
496      HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool)
497#undef HANDLE_PRIMITIVE_TYPE
498
499#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD)                       \
500      case FieldDescriptor::TYPE_##TYPE:                                     \
501        WireFormatLite::Write##TYPE_METHOD(                                  \
502              field->number(),                                               \
503              field->is_repeated() ?                                         \
504                message_reflection->GetRepeated##CPPTYPE_METHOD(             \
505                  message, field, j) :                                       \
506                message_reflection->Get##CPPTYPE_METHOD(message, field),     \
507              output);                                                       \
508        break;
509
510      HANDLE_TYPE(GROUP  , Group  , Message)
511      HANDLE_TYPE(MESSAGE, Message, Message)
512#undef HANDLE_TYPE
513
514      case FieldDescriptor::TYPE_ENUM: {
515        const EnumValueDescriptor* value = field->is_repeated() ?
516          message_reflection->GetRepeatedEnum(message, field, j) :
517          message_reflection->GetEnum(message, field);
518        if (is_packed) {
519          WireFormatLite::WriteEnumNoTag(value->number(), output);
520        } else {
521          WireFormatLite::WriteEnum(field->number(), value->number(), output);
522        }
523        break;
524      }
525
526      // Handle strings separately so that we can get string references
527      // instead of copying.
528      case FieldDescriptor::TYPE_STRING: {
529        string scratch;
530        const string& value = field->is_repeated() ?
531          message_reflection->GetRepeatedStringReference(
532            message, field, j, &scratch) :
533          message_reflection->GetStringReference(message, field, &scratch);
534        VerifyUTF8String(value.data(), value.length(), SERIALIZE);
535        WireFormatLite::WriteString(field->number(), value, output);
536        break;
537      }
538
539      case FieldDescriptor::TYPE_BYTES: {
540        string scratch;
541        const string& value = field->is_repeated() ?
542          message_reflection->GetRepeatedStringReference(
543            message, field, j, &scratch) :
544          message_reflection->GetStringReference(message, field, &scratch);
545        WireFormatLite::WriteBytes(field->number(), value, output);
546        break;
547      }
548    }
549  }
550}
551
552void WireFormat::SerializeMessageSetItemWithCachedSizes(
553    const FieldDescriptor* field,
554    const Message& message,
555    io::CodedOutputStream* output) {
556  const Reflection* message_reflection = message.GetReflection();
557
558  // Start group.
559  output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
560
561  // Write type ID.
562  output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
563  output->WriteVarint32(field->number());
564
565  // Write message.
566  output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
567
568  const Message& sub_message = message_reflection->GetMessage(message, field);
569  output->WriteVarint32(sub_message.GetCachedSize());
570  sub_message.SerializeWithCachedSizes(output);
571
572  // End group.
573  output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
574}
575
576// ===================================================================
577
578int WireFormat::ByteSize(const Message& message) {
579  const Descriptor* descriptor = message.GetDescriptor();
580  const Reflection* message_reflection = message.GetReflection();
581
582  int our_size = 0;
583
584  vector<const FieldDescriptor*> fields;
585  message_reflection->ListFields(message, &fields);
586  for (int i = 0; i < fields.size(); i++) {
587    our_size += FieldByteSize(fields[i], message);
588  }
589
590  if (descriptor->options().message_set_wire_format()) {
591    our_size += WireFormatLite::ComputeUnknownMessageSetItemsSize(
592      message_reflection->GetUnknownFields(message));
593  } else {
594    our_size += WireFormatLite::ComputeUnknownFieldsSize(
595      message_reflection->GetUnknownFields(message));
596  }
597
598  return our_size;
599}
600
601int WireFormat::FieldByteSize(
602    const FieldDescriptor* field,
603    const Message& message) {
604  const Reflection* message_reflection = message.GetReflection();
605
606  if (field->is_extension() &&
607      field->containing_type()->options().message_set_wire_format() &&
608      field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
609      !field->is_repeated()) {
610    return MessageSetItemByteSize(field, message);
611  }
612
613  int count = 0;
614  if (field->is_repeated()) {
615    count = message_reflection->FieldSize(message, field);
616  } else if (message_reflection->HasField(message, field)) {
617    count = 1;
618  }
619
620  const int data_size = FieldDataOnlyByteSize(field, message);
621  int our_size = data_size;
622  if (field->options().packed()) {
623    if (data_size > 0) {
624      // Packed fields get serialized like a string, not their native type.
625      // Technically this doesn't really matter; the size only changes if it's
626      // a GROUP
627      our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING);
628      our_size += io::CodedOutputStream::VarintSize32(data_size);
629    }
630  } else {
631    our_size += count * TagSize(field->number(), field->type());
632  }
633  return our_size;
634}
635
636int WireFormat::FieldDataOnlyByteSize(
637    const FieldDescriptor* field,
638    const Message& message) {
639  const Reflection* message_reflection = message.GetReflection();
640
641  int count = 0;
642  if (field->is_repeated()) {
643    count = message_reflection->FieldSize(message, field);
644  } else if (message_reflection->HasField(message, field)) {
645    count = 1;
646  }
647
648  int data_size = 0;
649  switch (field->type()) {
650#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD)                     \
651    case FieldDescriptor::TYPE_##TYPE:                                     \
652      if (field->is_repeated()) {                                          \
653        for (int j = 0; j < count; j++) {                                  \
654          data_size += WireFormatLite::TYPE_METHOD##Size(                  \
655            message_reflection->GetRepeated##CPPTYPE_METHOD(               \
656              message, field, j));                                         \
657        }                                                                  \
658      } else {                                                             \
659        data_size += WireFormatLite::TYPE_METHOD##Size(                    \
660          message_reflection->Get##CPPTYPE_METHOD(message, field));        \
661      }                                                                    \
662      break;
663
664#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD)                               \
665    case FieldDescriptor::TYPE_##TYPE:                                     \
666      data_size += count * WireFormatLite::k##TYPE_METHOD##Size;           \
667      break;
668
669    HANDLE_TYPE( INT32,  Int32,  Int32)
670    HANDLE_TYPE( INT64,  Int64,  Int64)
671    HANDLE_TYPE(SINT32, SInt32,  Int32)
672    HANDLE_TYPE(SINT64, SInt64,  Int64)
673    HANDLE_TYPE(UINT32, UInt32, UInt32)
674    HANDLE_TYPE(UINT64, UInt64, UInt64)
675
676    HANDLE_FIXED_TYPE( FIXED32,  Fixed32)
677    HANDLE_FIXED_TYPE( FIXED64,  Fixed64)
678    HANDLE_FIXED_TYPE(SFIXED32, SFixed32)
679    HANDLE_FIXED_TYPE(SFIXED64, SFixed64)
680
681    HANDLE_FIXED_TYPE(FLOAT , Float )
682    HANDLE_FIXED_TYPE(DOUBLE, Double)
683
684    HANDLE_FIXED_TYPE(BOOL, Bool)
685
686    HANDLE_TYPE(GROUP  , Group  , Message)
687    HANDLE_TYPE(MESSAGE, Message, Message)
688#undef HANDLE_TYPE
689#undef HANDLE_FIXED_TYPE
690
691    case FieldDescriptor::TYPE_ENUM: {
692      if (field->is_repeated()) {
693        for (int j = 0; j < count; j++) {
694          data_size += WireFormatLite::EnumSize(
695            message_reflection->GetRepeatedEnum(message, field, j)->number());
696        }
697      } else {
698        data_size += WireFormatLite::EnumSize(
699          message_reflection->GetEnum(message, field)->number());
700      }
701      break;
702    }
703
704    // Handle strings separately so that we can get string references
705    // instead of copying.
706    case FieldDescriptor::TYPE_STRING:
707    case FieldDescriptor::TYPE_BYTES: {
708      for (int j = 0; j < count; j++) {
709        string scratch;
710        const string& value = field->is_repeated() ?
711          message_reflection->GetRepeatedStringReference(
712            message, field, j, &scratch) :
713          message_reflection->GetStringReference(message, field, &scratch);
714        data_size += WireFormatLite::StringSize(value);
715      }
716      break;
717    }
718  }
719  return data_size;
720}
721
722int WireFormat::MessageSetItemByteSize(
723    const FieldDescriptor* field,
724    const Message& message) {
725  const Reflection* message_reflection = message.GetReflection();
726
727  int our_size = WireFormatLite::kMessageSetItemTagsSize;
728
729  // type_id
730  our_size += io::CodedOutputStream::VarintSize32(field->number());
731
732  // message
733  const Message& sub_message = message_reflection->GetMessage(message, field);
734  int message_size = sub_message.ByteSize();
735
736  our_size += io::CodedOutputStream::VarintSize32(message_size);
737  our_size += message_size;
738
739  return our_size;
740}
741
742void WireFormat::VerifyUTF8StringFallback(const char* data,
743                                          int size,
744                                          Operation op) {
745  if (!IsStructurallyValidUTF8(data, size)) {
746    const char* operation_str = NULL;
747    switch (op) {
748      case PARSE:
749        operation_str = "parsing";
750        break;
751      case SERIALIZE:
752        operation_str = "serializing";
753        break;
754      // no default case: have the compiler warn if a case is not covered.
755    }
756    GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when "
757               << operation_str
758               << " a protocol buffer. Use the 'bytes' type if you intend to "
759                  "send raw bytes.";
760  }
761}
762
763
764}  // namespace internal
765}  // namespace protobuf
766}  // namespace google
767