aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/generated_message_reflection.cc
diff options
context:
space:
mode:
authorGravatar temporal <temporal@630680e5-0e50-0410-840e-4b1c322b438d>2008-07-10 02:12:20 +0000
committerGravatar temporal <temporal@630680e5-0e50-0410-840e-4b1c322b438d>2008-07-10 02:12:20 +0000
commit40ee551715c3a784ea6132dbf604b0e665ca2def (patch)
tree6e3ea9674be5b0f59106f88f3afa1313854beebf /src/google/protobuf/generated_message_reflection.cc
Initial checkin.
Diffstat (limited to 'src/google/protobuf/generated_message_reflection.cc')
-rw-r--r--src/google/protobuf/generated_message_reflection.cc665
1 files changed, 665 insertions, 0 deletions
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
new file mode 100644
index 00000000..ec17572b
--- /dev/null
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -0,0 +1,665 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <algorithm>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace { const string kEmptyString; }
+
+// ===================================================================
+// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
+// a string field).
+
+namespace {
+
+void ReportReflectionUsageError(
+ const Descriptor* descriptor, const FieldDescriptor* field,
+ const char* method, const char* description) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer reflection usage error:\n"
+ " Method : google::protobuf::Message::Reflection::" << method << "\n"
+ " Message type: " << descriptor->full_name() << "\n"
+ " Field : " << field->full_name() << "\n"
+ " Problem : " << description;
+}
+
+const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = {
+ "INVALID_CPPTYPE",
+ "CPPTYPE_INT32",
+ "CPPTYPE_INT64",
+ "CPPTYPE_UINT32",
+ "CPPTYPE_UINT64",
+ "CPPTYPE_DOUBLE",
+ "CPPTYPE_FLOAT",
+ "CPPTYPE_BOOL",
+ "CPPTYPE_ENUM",
+ "CPPTYPE_STRING",
+ "CPPTYPE_MESSAGE"
+};
+
+static void ReportReflectionUsageTypeError(
+ const Descriptor* descriptor, const FieldDescriptor* field,
+ const char* method,
+ FieldDescriptor::CppType expected_type) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer reflection usage error:\n"
+ " Method : google::protobuf::Message::Reflection::" << method << "\n"
+ " Message type: " << descriptor->full_name() << "\n"
+ " Field : " << field->full_name() << "\n"
+ " Problem : Field is not the right type for this message:\n"
+ " Expected : " << cpptype_names_[expected_type] << "\n"
+ " Field type: " << cpptype_names_[field->cpp_type()];
+}
+
+static void ReportReflectionUsageEnumTypeError(
+ const Descriptor* descriptor, const FieldDescriptor* field,
+ const char* method, const EnumValueDescriptor* value) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer reflection usage error:\n"
+ " Method : google::protobuf::Message::Reflection::" << method << "\n"
+ " Message type: " << descriptor->full_name() << "\n"
+ " Field : " << field->full_name() << "\n"
+ " Problem : Enum value did not match field type:\n"
+ " Expected : " << field->enum_type()->full_name() << "\n"
+ " Actual : " << value->full_name();
+}
+
+#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \
+ if (!(CONDITION)) \
+ ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION)
+#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \
+ USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION)
+#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \
+ USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION)
+
+#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \
+ if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \
+ ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \
+ FieldDescriptor::CPPTYPE_##CPPTYPE)
+
+#define USAGE_CHECK_ENUM_VALUE(METHOD) \
+ if (value->type() != field->enum_type()) \
+ ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value)
+
+#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \
+ USAGE_CHECK_EQ(field->containing_type(), descriptor_, \
+ METHOD, "Field does not match message type.");
+#define USAGE_CHECK_SINGULAR(METHOD) \
+ USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
+ "Field is repeated; the method requires a singular field.")
+#define USAGE_CHECK_REPEATED(METHOD) \
+ USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \
+ "Field is singular; the method requires a repeated field.")
+
+#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \
+ USAGE_CHECK_MESSAGE_TYPE(METHOD); \
+ USAGE_CHECK_##LABEL(METHOD); \
+ USAGE_CHECK_TYPE(METHOD, CPPTYPE)
+
+} // namespace
+
+// ===================================================================
+
+GeneratedMessageReflection::GeneratedMessageReflection(
+ const Descriptor* descriptor,
+ void* base, const void* default_base,
+ const int offsets[], uint32 has_bits[],
+ ExtensionSet* extensions)
+ : descriptor_ (descriptor),
+ base_ (base),
+ default_base_(default_base),
+ offsets_ (offsets),
+ has_bits_ (has_bits),
+ extensions_ (extensions) {
+}
+
+GeneratedMessageReflection::~GeneratedMessageReflection() {}
+
+const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields() const {
+ return unknown_fields_;
+}
+UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields() {
+ return &unknown_fields_;
+}
+
+// -------------------------------------------------------------------
+
+bool GeneratedMessageReflection::HasField(const FieldDescriptor* field) const {
+ USAGE_CHECK_MESSAGE_TYPE(HasField);
+ USAGE_CHECK_SINGULAR(HasField);
+
+ if (field->is_extension()) {
+ return extensions_->Has(field->number());
+ } else {
+ return HasBit(field);
+ }
+}
+
+int GeneratedMessageReflection::FieldSize(const FieldDescriptor* field) const {
+ USAGE_CHECK_MESSAGE_TYPE(HasField);
+ USAGE_CHECK_REPEATED(HasField);
+
+ if (field->is_extension()) {
+ return extensions_->ExtensionSize(field->number());
+ } else {
+ return GetRaw<GenericRepeatedField>(field).GenericSize();
+ }
+}
+
+void GeneratedMessageReflection::ClearField(const FieldDescriptor* field) {
+ USAGE_CHECK_MESSAGE_TYPE(ClearField);
+
+ if (field->is_extension()) {
+ extensions_->ClearExtension(field->number());
+ } else if (!field->is_repeated()) {
+ if (HasBit(field)) {
+ ClearBit(field);
+
+ // We need to set the field back to its default value.
+ switch (field->cpp_type()) {
+#define CLEAR_TYPE(CPPTYPE, TYPE) \
+ case FieldDescriptor::CPPTYPE_##CPPTYPE: \
+ *MutableRaw<TYPE>(field) = field->default_value_##TYPE(); \
+ break;
+
+ CLEAR_TYPE(INT32 , int32 );
+ CLEAR_TYPE(INT64 , int64 );
+ CLEAR_TYPE(UINT32, uint32);
+ CLEAR_TYPE(UINT64, uint64);
+ CLEAR_TYPE(FLOAT , float );
+ CLEAR_TYPE(DOUBLE, double);
+ CLEAR_TYPE(BOOL , bool );
+#undef CLEAR_TYPE
+
+ case FieldDescriptor::CPPTYPE_ENUM:
+ *MutableRaw<int>(field) = field->default_value_enum()->number();
+ break;
+
+ case FieldDescriptor::CPPTYPE_STRING: {
+ const string* default_ptr = DefaultRaw<const string*>(field);
+ string** value = MutableRaw<string*>(field);
+ if (*value != default_ptr) {
+ if (field->has_default_value()) {
+ (*value)->assign(field->default_value_string());
+ } else {
+ (*value)->clear();
+ }
+ }
+ break;
+ }
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ (*MutableRaw<Message*>(field))->Clear();
+ break;
+ }
+ }
+ } else {
+ MutableRaw<GenericRepeatedField>(field)->GenericClear();
+ }
+}
+
+namespace {
+// Comparison functor for sorting FieldDescriptors by field number.
+struct FieldNumberSorter {
+ bool operator()(const FieldDescriptor* left,
+ const FieldDescriptor* right) const {
+ return left->number() < right->number();
+ }
+};
+} // namespace
+
+void GeneratedMessageReflection::ListFields(
+ vector<const FieldDescriptor*>* output) const {
+ output->clear();
+
+ // Optimization: The default instance never has any fields set.
+ if (base_ == default_base_) return;
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->is_repeated()) {
+ if (GetRaw<GenericRepeatedField>(field).GenericSize() > 0) {
+ output->push_back(field);
+ }
+ } else {
+ if (HasBit(field)) {
+ output->push_back(field);
+ }
+ }
+ }
+
+ if (extensions_ != NULL) {
+ extensions_->AppendToList(output);
+ }
+
+ // ListFields() must sort output by field number.
+ sort(output->begin(), output->end(), FieldNumberSorter());
+}
+
+// -------------------------------------------------------------------
+
+#undef DEFINE_PRIMITIVE_ACCESSORS
+#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \
+ PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \
+ const FieldDescriptor* field) const { \
+ USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
+ if (field->is_extension()) { \
+ return extensions_->Get##TYPENAME(field->number()); \
+ } else { \
+ return GetField<TYPE>(field); \
+ } \
+ } \
+ \
+ void GeneratedMessageReflection::Set##TYPENAME( \
+ const FieldDescriptor* field, PASSTYPE value) { \
+ USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
+ if (field->is_extension()) { \
+ return extensions_->Set##TYPENAME(field->number(), value); \
+ } else { \
+ SetField<TYPE>(field, value); \
+ } \
+ } \
+ \
+ PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \
+ const FieldDescriptor* field, int index) const { \
+ USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \
+ if (field->is_extension()) { \
+ return extensions_->GetRepeated##TYPENAME(field->number(), index); \
+ } else { \
+ return GetRepeatedField<TYPE>(field, index); \
+ } \
+ } \
+ \
+ void GeneratedMessageReflection::SetRepeated##TYPENAME( \
+ const FieldDescriptor* field, int index, PASSTYPE value) { \
+ USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \
+ if (field->is_extension()) { \
+ extensions_->SetRepeated##TYPENAME(field->number(), index, value); \
+ } else { \
+ SetRepeatedField<TYPE>(field, index, value); \
+ } \
+ } \
+ \
+ void GeneratedMessageReflection::Add##TYPENAME( \
+ const FieldDescriptor* field, PASSTYPE value) { \
+ USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
+ if (field->is_extension()) { \
+ extensions_->Add##TYPENAME(field->number(), value); \
+ } else { \
+ AddField<TYPE>(field, value); \
+ } \
+ }
+
+DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 )
+DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 )
+DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32)
+DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64)
+DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT )
+DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE)
+DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL )
+#undef DEFINE_PRIMITIVE_ACCESSORS
+
+// -------------------------------------------------------------------
+
+string GeneratedMessageReflection::GetString(
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
+ if (field->is_extension()) {
+ return extensions_->GetString(field->number());
+ } else {
+ return *GetField<const string*>(field);
+ }
+}
+
+const string& GeneratedMessageReflection::GetStringReference(
+ const FieldDescriptor* field, string* scratch) const {
+ USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
+ if (field->is_extension()) {
+ return extensions_->GetString(field->number());
+ } else {
+ return *GetField<const string*>(field);
+ }
+}
+
+
+void GeneratedMessageReflection::SetString(
+ const FieldDescriptor* field, const string& value) {
+ USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
+ if (field->is_extension()) {
+ return extensions_->SetString(field->number(), value);
+ } else {
+ string** ptr = MutableField<string*>(field);
+ if (*ptr == DefaultRaw<const string*>(field)) {
+ *ptr = new string(value);
+ } else {
+ (*ptr)->assign(value);
+ }
+ }
+}
+
+
+string GeneratedMessageReflection::GetRepeatedString(
+ const FieldDescriptor* field, int index) const {
+ USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
+ if (field->is_extension()) {
+ return extensions_->GetRepeatedString(field->number(), index);
+ } else {
+ return GetRepeatedField<string>(field, index);
+ }
+}
+
+const string& GeneratedMessageReflection::GetRepeatedStringReference(
+ const FieldDescriptor* field, int index, string* scratch) const {
+ USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
+ if (field->is_extension()) {
+ return extensions_->GetRepeatedString(field->number(), index);
+ } else {
+ return GetRepeatedField<string>(field, index);
+ }
+}
+
+
+void GeneratedMessageReflection::SetRepeatedString(
+ const FieldDescriptor* field, int index, const string& value) {
+ USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
+ if (field->is_extension()) {
+ extensions_->SetRepeatedString(field->number(), index, value);
+ } else {
+ SetRepeatedField<string>(field, index, value);
+ }
+}
+
+
+void GeneratedMessageReflection::AddString(
+ const FieldDescriptor* field, const string& value) {
+ USAGE_CHECK_ALL(AddString, REPEATED, STRING);
+ if (field->is_extension()) {
+ extensions_->AddString(field->number(), value);
+ } else {
+ AddField<string>(field, value);
+ }
+}
+
+
+// -------------------------------------------------------------------
+
+const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
+
+ int value;
+ if (field->is_extension()) {
+ value = extensions_->GetEnum(field->number());
+ } else {
+ value = GetField<int>(field);
+ }
+ const EnumValueDescriptor* result =
+ field->enum_type()->FindValueByNumber(value);
+ GOOGLE_CHECK(result != NULL);
+ return result;
+}
+
+void GeneratedMessageReflection::SetEnum(const FieldDescriptor* field,
+ const EnumValueDescriptor* value) {
+ USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
+ USAGE_CHECK_ENUM_VALUE(SetEnum);
+
+ if (field->is_extension()) {
+ extensions_->SetEnum(field->number(), value->number());
+ } else {
+ SetField<int>(field, value->number());
+ }
+}
+
+const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
+ const FieldDescriptor* field, int index) const {
+ USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
+
+ int value;
+ if (field->is_extension()) {
+ value = extensions_->GetRepeatedEnum(field->number(), index);
+ } else {
+ value = GetRepeatedField<int>(field, index);
+ }
+ const EnumValueDescriptor* result =
+ field->enum_type()->FindValueByNumber(value);
+ GOOGLE_CHECK(result != NULL);
+ return result;
+}
+
+void GeneratedMessageReflection::SetRepeatedEnum(
+ const FieldDescriptor* field, int index,
+ const EnumValueDescriptor* value) {
+ USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
+ USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
+
+ if (field->is_extension()) {
+ extensions_->SetRepeatedEnum(field->number(), index, value->number());
+ } else {
+ SetRepeatedField<int>(field, index, value->number());
+ }
+}
+
+void GeneratedMessageReflection::AddEnum(const FieldDescriptor* field,
+ const EnumValueDescriptor* value) {
+ USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
+ USAGE_CHECK_ENUM_VALUE(AddEnum);
+
+ if (field->is_extension()) {
+ extensions_->AddEnum(field->number(), value->number());
+ } else {
+ AddField<int>(field, value->number());
+ }
+}
+
+// -------------------------------------------------------------------
+
+const Message& GeneratedMessageReflection::GetMessage(
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
+
+ if (field->is_extension()) {
+ return extensions_->GetMessage(field->number());
+ } else {
+ const Message* result = GetRaw<const Message*>(field);
+ if (result == NULL) {
+ result = DefaultRaw<const Message*>(field);
+ }
+ return *result;
+ }
+}
+
+Message* GeneratedMessageReflection::MutableMessage(
+ const FieldDescriptor* field) {
+ USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+
+ if (field->is_extension()) {
+ return extensions_->MutableMessage(field->number());
+ } else {
+ Message** result = MutableField<Message*>(field);
+ if (*result == NULL) {
+ const Message* default_message = DefaultRaw<const Message*>(field);
+ *result = default_message->New();
+ (*result)->CopyFrom(*default_message);
+ }
+ return *result;
+ }
+}
+
+const Message& GeneratedMessageReflection::GetRepeatedMessage(
+ const FieldDescriptor* field, int index) const {
+ USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ return extensions_->GetRepeatedMessage(field->number(), index);
+ } else {
+ return GetRepeatedField<Message>(field, index);
+ }
+}
+
+Message* GeneratedMessageReflection::MutableRepeatedMessage(
+ const FieldDescriptor* field, int index) {
+ USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ return extensions_->MutableRepeatedMessage(field->number(), index);
+ } else {
+ return MutableRepeatedField<Message>(field, index);
+ }
+}
+
+Message* GeneratedMessageReflection::AddMessage(const FieldDescriptor* field) {
+ USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ return extensions_->AddMessage(field->number());
+ } else {
+ return AddField<Message>(field);
+ }
+}
+
+// -------------------------------------------------------------------
+
+const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
+ const string& name) const {
+ if (extensions_ == NULL) return NULL;
+ return extensions_->FindKnownExtensionByName(name);
+}
+
+const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
+ int number) const {
+ if (extensions_ == NULL) return NULL;
+ return extensions_->FindKnownExtensionByNumber(number);
+}
+
+// ===================================================================
+// Some private helpers.
+
+// These simple template accessors obtain pointers (or references) to
+// the given field.
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetRaw(
+ const FieldDescriptor* field) const {
+ const void* ptr = reinterpret_cast<const uint8*>(base_) +
+ offsets_[field->index()];
+ return *reinterpret_cast<const Type*>(ptr);
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::MutableRaw(
+ const FieldDescriptor* field) {
+ void* ptr = reinterpret_cast<uint8*>(base_) + offsets_[field->index()];
+ return reinterpret_cast<Type*>(ptr);
+}
+
+template <typename Type>
+inline const Type& GeneratedMessageReflection::DefaultRaw(
+ const FieldDescriptor* field) const {
+ const void* ptr = reinterpret_cast<const uint8*>(default_base_) +
+ offsets_[field->index()];
+ return *reinterpret_cast<const Type*>(ptr);
+}
+
+// Simple accessors for manipulating has_bits_.
+inline bool GeneratedMessageReflection::HasBit(
+ const FieldDescriptor* field) const {
+ return has_bits_[field->index() / 32] & (1 << (field->index() % 32));
+}
+
+inline void GeneratedMessageReflection::SetBit(
+ const FieldDescriptor* field) {
+ has_bits_[field->index() / 32] |= (1 << (field->index() % 32));
+}
+
+inline void GeneratedMessageReflection::ClearBit(
+ const FieldDescriptor* field) {
+ has_bits_[field->index() / 32] &= ~(1 << (field->index() % 32));
+}
+
+// Template implementations of basic accessors. Inline because each
+// template instance is only called from one location. These are
+// used for all types except messages.
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetField(
+ const FieldDescriptor* field) const {
+ return GetRaw<Type>(field);
+}
+
+template <typename Type>
+inline void GeneratedMessageReflection::SetField(
+ const FieldDescriptor* field, const Type& value) {
+ *MutableRaw<Type>(field) = value;
+ SetBit(field);
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::MutableField(
+ const FieldDescriptor* field) {
+ SetBit(field);
+ return MutableRaw<Type>(field);
+}
+
+template <typename Type>
+inline const Type& GeneratedMessageReflection::GetRepeatedField(
+ const FieldDescriptor* field, int index) const {
+ return *reinterpret_cast<const Type*>(
+ GetRaw<GenericRepeatedField>(field).GenericGet(index));
+}
+
+template <typename Type>
+inline void GeneratedMessageReflection::SetRepeatedField(
+ const FieldDescriptor* field, int index, const Type& value) {
+ GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
+ *reinterpret_cast<Type*>(repeated->GenericMutable(index)) = value;
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::MutableRepeatedField(
+ const FieldDescriptor* field, int index) {
+ GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
+ return reinterpret_cast<Type*>(repeated->GenericMutable(index));
+}
+
+template <typename Type>
+inline void GeneratedMessageReflection::AddField(
+ const FieldDescriptor* field, const Type& value) {
+ GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
+ *reinterpret_cast<Type*>(repeated->GenericAdd()) = value;
+}
+
+template <typename Type>
+inline Type* GeneratedMessageReflection::AddField(
+ const FieldDescriptor* field) {
+ GenericRepeatedField* repeated = MutableRaw<GenericRepeatedField>(field);
+ return reinterpret_cast<Type*>(repeated->GenericAdd());
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google