| Index: third_party/protobuf/src/google/protobuf/descriptor.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/descriptor.cc b/third_party/protobuf/src/google/protobuf/descriptor.cc
|
| index 6c9648b522987cd30156d09feedf6d776b5a18a2..b58a22b32240d06b1b749a896e7c9a1c91ad4829 100644
|
| --- a/third_party/protobuf/src/google/protobuf/descriptor.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/descriptor.cc
|
| @@ -42,10 +42,12 @@
|
| #include <google/protobuf/descriptor.h>
|
| #include <google/protobuf/descriptor_database.h>
|
| #include <google/protobuf/descriptor.pb.h>
|
| +#include <google/protobuf/dynamic_message.h>
|
| #include <google/protobuf/text_format.h>
|
| #include <google/protobuf/unknown_field_set.h>
|
| #include <google/protobuf/wire_format.h>
|
| #include <google/protobuf/io/coded_stream.h>
|
| +#include <google/protobuf/io/tokenizer.h>
|
| #include <google/protobuf/io/zero_copy_stream_impl.h>
|
| #include <google/protobuf/stubs/common.h>
|
| #include <google/protobuf/stubs/once.h>
|
| @@ -2056,6 +2058,8 @@ class DescriptorBuilder {
|
| // Otherwise returns true.
|
| bool InterpretOptions(OptionsToInterpret* options_to_interpret);
|
|
|
| + class AggregateOptionFinder;
|
| +
|
| private:
|
| // Interprets uninterpreted_option_ on the specified message, which
|
| // must be the mutable copy of the original options message to which
|
| @@ -2082,6 +2086,11 @@ class DescriptorBuilder {
|
| bool SetOptionValue(const FieldDescriptor* option_field,
|
| UnknownFieldSet* unknown_fields);
|
|
|
| + // Parses an aggregate value for a CPPTYPE_MESSAGE option and
|
| + // saves it into *unknown_fields.
|
| + bool SetAggregateOption(const FieldDescriptor* option_field,
|
| + UnknownFieldSet* unknown_fields);
|
| +
|
| // Convenience functions to set an int field the right way, depending on
|
| // its wire type (a single int CppType can represent multiple wire types).
|
| void SetInt32(int number, int32 value, FieldDescriptor::Type type,
|
| @@ -2128,6 +2137,10 @@ class DescriptorBuilder {
|
| // can use it to find locations recorded by the parser.
|
| const UninterpretedOption* uninterpreted_option_;
|
|
|
| + // Factory used to create the dynamic messages we need to parse
|
| + // any aggregate option values we encounter.
|
| + DynamicMessageFactory dynamic_factory_;
|
| +
|
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
|
| };
|
|
|
| @@ -2139,6 +2152,8 @@ class DescriptorBuilder {
|
| // redundantly declare OptionInterpreter a friend just to make things extra
|
| // clear for these bad compilers.
|
| friend class OptionInterpreter;
|
| + friend class OptionInterpreter::AggregateOptionFinder;
|
| +
|
| static inline bool get_allow_unknown(const DescriptorPool* pool) {
|
| return pool->allow_unknown_;
|
| }
|
| @@ -3973,9 +3988,6 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
|
| intermediate_fields.push_back(field);
|
| descriptor = field->message_type();
|
| }
|
| - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| - return AddNameError("Option field \"" + debug_msg_name +
|
| - "\" cannot be of message type.");
|
| }
|
| }
|
|
|
| @@ -4310,18 +4322,95 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
|
| break;
|
|
|
| case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - // We don't currently support defining a message-typed option, so we
|
| - // should never actually get here.
|
| - return AddValueError("Option \"" + option_field->full_name() +
|
| - "\" is a message. To set fields within it, use "
|
| - "syntax like \"" + option_field->name() +
|
| - ".foo = value\".");
|
| + if (!SetAggregateOption(option_field, unknown_fields)) {
|
| + return false;
|
| + }
|
| break;
|
| }
|
|
|
| return true;
|
| }
|
|
|
| +class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
|
| + : public TextFormat::Finder {
|
| + public:
|
| + DescriptorBuilder* builder_;
|
| +
|
| + virtual const FieldDescriptor* FindExtension(
|
| + Message* message, const string& name) const {
|
| + if (builder_->pool_->mutex_ != NULL) {
|
| + builder_->pool_->mutex_->AssertHeld();
|
| + }
|
| + Symbol result = builder_->LookupSymbolNoPlaceholder(
|
| + name, message->GetDescriptor()->full_name());
|
| + if (result.type == Symbol::FIELD &&
|
| + result.field_descriptor->is_extension()) {
|
| + return result.field_descriptor;
|
| + } else {
|
| + return NULL;
|
| + }
|
| + }
|
| +};
|
| +
|
| +// A custom error collector to record any text-format parsing errors
|
| +namespace {
|
| +class AggregateErrorCollector : public io::ErrorCollector {
|
| + public:
|
| + string error_;
|
| +
|
| + virtual void AddError(int line, int column, const string& message) {
|
| + if (!error_.empty()) {
|
| + error_ += "; ";
|
| + }
|
| + error_ += message;
|
| + }
|
| +
|
| + virtual void AddWarning(int line, int column, const string& message) {
|
| + // Ignore warnings
|
| + }
|
| +};
|
| +}
|
| +
|
| +// We construct a dynamic message of the type corresponding to
|
| +// option_field, parse the supplied text-format string into this
|
| +// message, and serialize the resulting message to produce the value.
|
| +bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
|
| + const FieldDescriptor* option_field,
|
| + UnknownFieldSet* unknown_fields) {
|
| + if (!uninterpreted_option_->has_aggregate_value()) {
|
| + return AddValueError("Option \"" + option_field->full_name() +
|
| + "\" is a message. To set the entire message, use "
|
| + "syntax like \"" + option_field->name() +
|
| + " = { <proto text format> }\". "
|
| + "To set fields within it, use "
|
| + "syntax like \"" + option_field->name() +
|
| + ".foo = value\".");
|
| + }
|
| +
|
| + const Descriptor* type = option_field->message_type();
|
| + scoped_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
|
| + GOOGLE_CHECK(dynamic.get() != NULL)
|
| + << "Could not create an instance of " << option_field->DebugString();
|
| +
|
| + AggregateErrorCollector collector;
|
| + AggregateOptionFinder finder;
|
| + finder.builder_ = builder_;
|
| + TextFormat::Parser parser;
|
| + parser.RecordErrorsTo(&collector);
|
| + parser.SetFinder(&finder);
|
| + if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
|
| + dynamic.get())) {
|
| + AddValueError("Error while parsing option value for \"" +
|
| + option_field->name() + "\": " + collector.error_);
|
| + return false;
|
| + } else {
|
| + string serial;
|
| + dynamic->SerializeToString(&serial); // Never fails
|
| + unknown_fields->AddLengthDelimited(option_field->number(), serial);
|
| + return true;
|
| + }
|
| +}
|
| +
|
| void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
|
| FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
|
| switch (type) {
|
|
|