Internal change.

PiperOrigin-RevId: 540118699
pull/13044/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent b1df92704b
commit c3edc9036d
  1. 2
      src/google/protobuf/BUILD.bazel
  2. 119
      src/google/protobuf/internal_message_util.cc
  3. 50
      src/google/protobuf/internal_message_util.h
  4. 45
      src/google/protobuf/internal_message_util_unittest.cc
  5. 2
      src/google/protobuf/message.h
  6. 3
      src/google/protobuf/unittest.proto

@ -425,6 +425,7 @@ cc_library(
"generated_message_reflection.cc", "generated_message_reflection.cc",
"generated_message_tctable_full.cc", "generated_message_tctable_full.cc",
"generated_message_tctable_gen.cc", "generated_message_tctable_gen.cc",
"internal_message_util.cc",
"map_field.cc", "map_field.cc",
"message.cc", "message.cc",
"reflection_mode.cc", "reflection_mode.cc",
@ -446,6 +447,7 @@ cc_library(
"generated_message_bases.h", "generated_message_bases.h",
"generated_message_reflection.h", "generated_message_reflection.h",
"generated_message_tctable_gen.h", "generated_message_tctable_gen.h",
"internal_message_util.h",
"map_entry.h", "map_entry.h",
"map_field.h", "map_field.h",
"map_field_inl.h", "map_field_inl.h",

@ -0,0 +1,119 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/internal_message_util.h"
#include <vector>
#include "google/protobuf/map_field.h"
namespace google {
namespace protobuf {
namespace internal {
class MessageUtil {
public:
static const internal::MapFieldBase* GetMapData(
const Reflection* reflection, const Message& message,
const FieldDescriptor* field) {
return reflection->GetMapData(message, field);
}
// Walks the entire message tree and eager parses all lazy fields.
static void EagerParseLazyField(Message* message);
};
namespace {
// Returns true if the field is a map that contains non-message value.
bool IsNonMessageMap(const FieldDescriptor* field) {
if (!field->is_map()) {
return false;
}
constexpr int kValueIndex = 1;
return field->message_type()->field(kValueIndex)->cpp_type() !=
FieldDescriptor::CPPTYPE_MESSAGE;
}
inline bool UseMapIterator(const Reflection* reflection, const Message& message,
const FieldDescriptor* field) {
return field->is_map() &&
MessageUtil::GetMapData(reflection, message, field)->IsMapValid();
}
inline bool IsNonMessageField(const FieldDescriptor* field) {
return field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE ||
IsNonMessageMap(field);
}
} // namespace
// To eagerly parse lazy fields in the entire message tree, mutates all the
// message fields (optional, repeated, extensions).
void MessageUtil::EagerParseLazyField(Message* message) {
const Reflection* reflection = message->GetReflection();
std::vector<const FieldDescriptor*> fields;
reflection->ListFields(*message, &fields);
for (const auto* field : fields) {
if (IsNonMessageField(field)) continue;
if (!field->is_repeated()) {
EagerParseLazyField(reflection->MutableMessage(message, field));
continue;
}
// Map values cannot be lazy but their child message may be.
if (UseMapIterator(reflection, *message, field)) {
auto end = reflection->MapEnd(message, field);
for (auto it = reflection->MapBegin(message, field); it != end; ++it) {
EagerParseLazyField(it.MutableValueRef()->MutableMessageValue());
}
continue;
}
// Repeated messages cannot be lazy but their child messages may be.
if (field->is_repeated()) {
for (int i = 0, end = reflection->FieldSize(*message, field); i < end;
++i) {
EagerParseLazyField(
reflection->MutableRepeatedMessage(message, field, i));
}
}
}
}
void EagerParseLazyField(Message& message) {
MessageUtil::EagerParseLazyField(&message);
}
} // namespace internal
} // namespace protobuf
} // namespace google

@ -0,0 +1,50 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This file contains miscellaneous (non-lite) helper code not suitable to
// generated_message_util.h. This should not be used directly by users.
#ifndef GOOGLE_PROTOBUF_INTERNAL_MESSAGE_UTIL_H__
#define GOOGLE_PROTOBUF_INTERNAL_MESSAGE_UTIL_H__
#include "google/protobuf/message.h"
namespace google {
namespace protobuf {
namespace internal {
// Walks the entire message tree and eager parses all lazy fields.
void EagerParseLazyField(Message& message);
} // namespace internal
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_INTERNAL_MESSAGE_UTIL_H__

@ -0,0 +1,45 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "google/protobuf/internal_message_util.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "google/protobuf/map_unittest.pb.h"
#include "google/protobuf/unittest.pb.h"
namespace google {
namespace protobuf {
namespace {
} // namespace
} // namespace protobuf
} // namespace google

@ -161,6 +161,7 @@ namespace internal {
struct FuzzPeer; struct FuzzPeer;
struct DescriptorTable; struct DescriptorTable;
class MapFieldBase; class MapFieldBase;
class MessageUtil;
class SwapFieldHelper; class SwapFieldHelper;
class CachedSize; class CachedSize;
struct TailCallTableInfo; struct TailCallTableInfo;
@ -1119,6 +1120,7 @@ class PROTOBUF_EXPORT Reflection final {
friend class expr::CelMapReflectionFriend; friend class expr::CelMapReflectionFriend;
friend class internal::MapFieldReflectionTest; friend class internal::MapFieldReflectionTest;
friend class internal::MapKeySorter; friend class internal::MapKeySorter;
friend class internal::MessageUtil;
friend class internal::WireFormat; friend class internal::WireFormat;
friend class internal::ReflectionOps; friend class internal::ReflectionOps;
friend class internal::SwapFieldHelper; friend class internal::SwapFieldHelper;

@ -588,6 +588,9 @@ message TestEagerMessage {
message TestLazyMessage { message TestLazyMessage {
optional TestAllTypes sub_message = 1 [lazy=true]; optional TestAllTypes sub_message = 1 [lazy=true];
} }
message TestLazyMessageRepeated {
repeated TestLazyMessage repeated_message = 1;
}
message TestEagerMaybeLazy { message TestEagerMaybeLazy {
message NestedMessage { message NestedMessage {
optional TestPackedTypes packed = 1; optional TestPackedTypes packed = 1;

Loading…
Cancel
Save