hpb: Introduce add_alias for repeated

Similar to set_alias for singular submessages, we augment hpb with the ability to add already-allocated messages via the generated function add_alias for repeated messages.

PiperOrigin-RevId: 684136800
pull/18646/head
Hong Shin 2 months ago committed by Copybara-Service
parent 213bb61292
commit 36075eafae
  1. 24
      hpb_generator/gen_repeated_fields.cc
  2. 4
      hpb_generator/tests/set_alias.proto
  3. 26
      hpb_generator/tests/test_generated.cc

@ -43,6 +43,7 @@ void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field,
output(
R"cc(
using $0Access::add_$1;
using $0Access::add_alias_$1;
using $0Access::mutable_$1;
)cc",
class_name, resolved_field_name);
@ -89,6 +90,12 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
const ::hpb::RepeatedField<const $4>::CProxy $2() const;
::hpb::Ptr<::hpb::RepeatedField<$4>> mutable_$2();
absl::StatusOr<$0> add_$2();
/**
* Re-points submsg of repeated field to given target.
*
* REQUIRES: both messages must be in the same arena.
*/
bool add_alias_$2($0 target);
$0 mutable_$2(size_t index) const;
)cc",
MessagePtrConstType(field, /* const */ false), // $0
@ -149,13 +156,26 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
if (!new_msg) {
return ::hpb::MessageAllocationError();
}
return hpb::interop::upb::MakeHandle<$4>((upb_Message*)new_msg, $5);
return hpb::interop::upb::MakeHandle<$4>((upb_Message *)new_msg, $5);
}
bool $0::add_alias_$2($1 target) {
ABSL_CHECK_EQ(arena_, hpb::interop::upb::GetArena(target));
size_t size = 0;
$3_$2(msg_, &size);
auto elements = $3_resize_$2(msg_, size + 1, arena_);
if (!elements) {
return false;
}
elements[size] = ($9 *)hpb::interop::upb::GetMessage(target);
return true;
}
)cc",
class_name, MessagePtrConstType(field, /* const */ false),
resolved_field_name, MessageName(message),
MessageBaseType(field, /* maybe_const */ false), arena_expression,
upbc_name);
upbc_name, ClassName(message), field->index(),
upb::generator::CApiMessageType(field->message_type()->full_name()));
output(
R"cc(
$1 $0::mutable_$2(size_t index) const {

@ -17,3 +17,7 @@ message Parent {
optional int32 x = 1;
optional Child child = 2;
}
message ParentWithRepeated {
repeated Child children = 1;
}

@ -41,6 +41,7 @@ using ::hpb_unittest::protos::container_ext;
using ::hpb_unittest::protos::ContainerExtension;
using ::hpb_unittest::protos::other_ext;
using ::hpb_unittest::protos::Parent;
using ::hpb_unittest::protos::ParentWithRepeated;
using ::hpb_unittest::protos::RED;
using ::hpb_unittest::protos::TestEnum;
using ::hpb_unittest::protos::TestModel;
@ -1273,4 +1274,29 @@ TEST(CppGeneratedCode, SetAliasFailsForDifferentArena) {
EXPECT_DEATH(parent.set_alias_child(child), "hpb::interop::upb::GetArena");
}
TEST(CppGeneratedCode, SetAliasRepeated) {
hpb::Arena arena;
auto child = hpb::CreateMessage<Child>(arena);
child.set_peeps(1611);
auto parent1 = hpb::CreateMessage<ParentWithRepeated>(arena);
auto parent2 = hpb::CreateMessage<ParentWithRepeated>(arena);
parent1.add_alias_children(child);
parent2.add_alias_children(child);
ASSERT_EQ(parent1.children(0)->peeps(), parent2.children(0)->peeps());
ASSERT_EQ(hpb::interop::upb::GetMessage(parent1.children(0)),
hpb::interop::upb::GetMessage(parent2.children(0)));
auto childPtr = hpb::Ptr<Child>(child);
ASSERT_EQ(hpb::interop::upb::GetMessage(childPtr),
hpb::interop::upb::GetMessage(parent1.children(0)));
}
TEST(CppGeneratedCode, SetAliasRepeatedFailsForDifferentArena) {
hpb::Arena arena;
auto child = hpb::CreateMessage<Child>(arena);
hpb::Arena different_arena;
auto parent = hpb::CreateMessage<ParentWithRepeated>(different_arena);
EXPECT_DEATH(parent.add_alias_children(child), "hpb::interop::upb::GetArena");
}
} // namespace

Loading…
Cancel
Save