diff --git a/hpb/hpb.h b/hpb/hpb.h index a3629ac584..5f53a44e91 100644 --- a/hpb/hpb.h +++ b/hpb/hpb.h @@ -42,6 +42,17 @@ typename T::Proxy CreateMessage(hpb::Arena& arena) { } template +typename T::Proxy CloneMessage(Ptr message, hpb::Arena& arena) { + return hpb::internal::PrivateAccess::Proxy( + hpb::internal::DeepClone(hpb::interop::upb::GetMessage(message), + T::minitable(), arena.ptr()), + arena.ptr()); +} + +// Deprecated; do not use. There is one extant caller which we plan to migrate. +// Tracking deletion TODO: b/385138477 +template +[[deprecated("Use CloneMessage(Ptr, hpb::Arena&) instead.")]] typename T::Proxy CloneMessage(Ptr message, upb_Arena* arena) { return ::hpb::internal::PrivateAccess::Proxy( ::hpb::internal::DeepClone(hpb::interop::upb::GetMessage(message), diff --git a/hpb_generator/tests/test_generated.cc b/hpb_generator/tests/test_generated.cc index 86e4de03fc..27931d91a0 100644 --- a/hpb_generator/tests/test_generated.cc +++ b/hpb_generator/tests/test_generated.cc @@ -625,6 +625,15 @@ TEST(CppGeneratedCode, ClearConstMessageShouldFailForConstChild) { EXPECT_TRUE(CanCallClearMessage()); } +TEST(CppGeneratedCode, CloneMessage) { + hpb::Arena arena; + TestModel model; + model.set_str1("Hello World"); + auto ptr = hpb::Ptr(&model); + hpb::Ptr cloned_model = hpb::CloneMessage(ptr, arena); + EXPECT_EQ(cloned_model->str1(), "Hello World"); +} + TEST(CppGeneratedCode, SetAlias) { hpb::Arena arena; auto child = hpb::CreateMessage(arena);