| Index: third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc b/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| index 547c9fb528469d76fb2dd3db79e3e7499e1df043..9dfcbd726bd9abfbdb0aeb6e9ab5dc3a3364ecb0 100644
|
| --- a/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/util/field_mask_util.cc
|
| @@ -200,6 +200,15 @@ class FieldMaskTree {
|
| MergeMessage(&root_, source, options, destination);
|
| }
|
|
|
| + // Trims all fields not specified by this tree from the given message.
|
| + void TrimMessage(Message* message) {
|
| + // Do nothing if the tree is empty.
|
| + if (root_.children.empty()) {
|
| + return;
|
| + }
|
| + TrimMessage(&root_, message);
|
| + }
|
| +
|
| private:
|
| struct Node {
|
| Node() {}
|
| @@ -233,6 +242,9 @@ class FieldMaskTree {
|
| const FieldMaskUtil::MergeOptions& options,
|
| Message* destination);
|
|
|
| + // Trims all fields not specified by this sub-tree from the given message.
|
| + void TrimMessage(const Node* node, Message* message);
|
| +
|
| Node root_;
|
|
|
| GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree);
|
| @@ -367,11 +379,15 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
|
| }
|
| if (!field->is_repeated()) {
|
| switch (field->cpp_type()) {
|
| -#define COPY_VALUE(TYPE, Name) \
|
| - case FieldDescriptor::CPPTYPE_##TYPE: { \
|
| - destination_reflection->Set##Name( \
|
| - destination, field, source_reflection->Get##Name(source, field)); \
|
| - break; \
|
| +#define COPY_VALUE(TYPE, Name) \
|
| + case FieldDescriptor::CPPTYPE_##TYPE: { \
|
| + if (source_reflection->HasField(source, field)) { \
|
| + destination_reflection->Set##Name( \
|
| + destination, field, source_reflection->Get##Name(source, field)); \
|
| + } else { \
|
| + destination_reflection->ClearField(destination, field); \
|
| + } \
|
| + break; \
|
| }
|
| COPY_VALUE(BOOL, Bool)
|
| COPY_VALUE(INT32, Int32)
|
| @@ -433,6 +449,27 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source,
|
| }
|
| }
|
|
|
| +void FieldMaskTree::TrimMessage(const Node* node, Message* message) {
|
| + GOOGLE_DCHECK(!node->children.empty());
|
| + const Reflection* reflection = message->GetReflection();
|
| + const Descriptor* descriptor = message->GetDescriptor();
|
| + const int32 field_count = descriptor->field_count();
|
| + for (int index = 0; index < field_count; ++index) {
|
| + const FieldDescriptor* field = descriptor->field(index);
|
| + map<string, Node*>::const_iterator it = node->children.find(field->name());
|
| + if (it == node->children.end()) {
|
| + reflection->ClearField(message, field);
|
| + } else {
|
| + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| + Node* child = it->second;
|
| + if (!child->children.empty()) {
|
| + TrimMessage(child, reflection->MutableMessage(message, field));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) {
|
| @@ -489,6 +526,14 @@ void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask,
|
| tree.MergeMessage(source, options, destination);
|
| }
|
|
|
| +void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination) {
|
| + // Build a FieldMaskTree and walk through the tree to merge all specified
|
| + // fields.
|
| + FieldMaskTree tree;
|
| + tree.MergeFromFieldMask(mask);
|
| + tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
|
| +}
|
| +
|
| } // namespace util
|
| } // namespace protobuf
|
| } // namespace google
|
|
|