diff --git a/hpb/backend/upb/BUILD b/hpb/backend/upb/BUILD index 71c430db01..007dcf7aac 100644 --- a/hpb/backend/upb/BUILD +++ b/hpb/backend/upb/BUILD @@ -32,6 +32,9 @@ cc_library( ], deps = [ "//hpb:ptr", + "//hpb/internal", + "//upb:mem", + "//upb:message", "//upb:mini_table", ], ) diff --git a/hpb/backend/upb/interop.h b/hpb/backend/upb/interop.h index 5cc338dae2..96816188d3 100644 --- a/hpb/backend/upb/interop.h +++ b/hpb/backend/upb/interop.h @@ -10,7 +10,10 @@ // The sole public header in hpb/backend/upb +#include "google/protobuf/hpb/internal/internal.h" #include "google/protobuf/hpb/ptr.h" +#include "upb/mem/arena.h" +#include "upb/message/message.h" #include "upb/mini_table/message.h" namespace hpb::interop::upb { @@ -25,6 +28,28 @@ const upb_MiniTable* GetMiniTable(Ptr) { return T::minitable(); } +/** + * Creates a const Handle to a upb message. + * + * The supplied arena must outlive the hpb handle. + * All messages reachable from from the upb message must + * outlive the hpb handle. + * + * That is: + * upb allows message M on arena A to point to message M' on + * arena A'. As a user of hpb, you must guarantee that both A and A' + * outlive M and M'. In practice, this is enforced by using upb::Fuse, + * or manual tracking. + * + * The upb message must not be mutated directly while the handle is alive. + * + * TODO: b/361596328 - revisit GetArena for CHandles + */ +template +typename T::CProxy MakeCHandle(const upb_Message* msg, upb_Arena* arena) { + return hpb::internal::PrivateAccess::CProxy(msg, arena); +} + } // namespace hpb::interop::upb #endif // GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__ diff --git a/hpb/hpb.h b/hpb/hpb.h index afc977b5c1..17ebfbfb1b 100644 --- a/hpb/hpb.h +++ b/hpb/hpb.h @@ -301,7 +301,7 @@ absl::StatusOr> GetExtension( return ExtensionNotFoundError( upb_MiniTableExtension_Number(id.mini_table_ext())); } - return Ptr(::hpb::internal::CreateMessage( + return Ptr(::hpb::interop::upb::MakeCHandle( (upb_Message*)value.msg_val, ::hpb::internal::GetArena(message))); } diff --git a/hpb/internal/internal.h b/hpb/internal/internal.h index bc00cafbdd..7c8f2374c3 100644 --- a/hpb/internal/internal.h +++ b/hpb/internal/internal.h @@ -43,11 +43,6 @@ typename T::Proxy CreateMessageProxy(upb_Message* msg, upb_Arena* arena) { return typename T::Proxy(msg, arena); } -template -typename T::CProxy CreateMessage(const upb_Message* msg, upb_Arena* arena) { - return PrivateAccess::CProxy(msg, arena); -} - } // namespace hpb::internal #endif // GOOGLE_PROTOBUF_HPB_INTERNAL_INTERNAL_H__ diff --git a/hpb/repeated_field.h b/hpb/repeated_field.h index fd5a5dec0c..7ea66c0e27 100644 --- a/hpb/repeated_field.h +++ b/hpb/repeated_field.h @@ -101,7 +101,7 @@ class RepeatedFieldProxy // T::CProxy [] operator specialization. typename T::CProxy operator[](size_t n) const { upb_MessageValue message_value = upb_Array_Get(this->arr_, n); - return ::hpb::internal::CreateMessage>( + return ::hpb::interop::upb::MakeCHandle>( (upb_Message*)message_value.msg_val, this->arena_); } diff --git a/hpb/repeated_field_iterator.h b/hpb/repeated_field_iterator.h index 19ae699504..1854f0545c 100644 --- a/hpb/repeated_field_iterator.h +++ b/hpb/repeated_field_iterator.h @@ -14,6 +14,7 @@ #include #include "absl/strings/string_view.h" +#include "google/protobuf/hpb/backend/upb/interop.h" #include "google/protobuf/hpb/hpb.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" @@ -354,8 +355,8 @@ struct MessageIteratorPolicy { void AddOffset(ptrdiff_t offset) { arr += offset; } auto Get() const { if constexpr (std::is_const_v) { - return ::hpb::internal::CreateMessage>( - *arr, arena); + return ::hpb::interop::upb::MakeCHandle< + typename std::remove_const_t>(*arr, arena); } else { return ::hpb::internal::CreateMessageProxy(*arr, arena); } diff --git a/hpb_generator/gen_accessors.cc b/hpb_generator/gen_accessors.cc index 0fd646fa2c..deb9a675da 100644 --- a/hpb_generator/gen_accessors.cc +++ b/hpb_generator/gen_accessors.cc @@ -244,7 +244,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) { if (!has_$2()) { return $4::default_instance(); } - return ::hpb::internal::CreateMessage<$4>( + return ::hpb::interop::upb::MakeCHandle<$4>( (upb_Message*)($3_$5(msg_)), arena_); } )cc", @@ -325,7 +325,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, $5* msg_value; $7bool success = $4_$9_get(msg_, $8, &msg_value); if (success) { - return ::hpb::internal::CreateMessage<$6>(UPB_UPCAST(msg_value), arena_); + return ::hpb::interop::upb::MakeCHandle<$6>(UPB_UPCAST(msg_value), arena_); } return absl::NotFoundError(""); } diff --git a/hpb_generator/gen_messages.cc b/hpb_generator/gen_messages.cc index 450aed5e02..ca4d11dd83 100644 --- a/hpb_generator/gen_messages.cc +++ b/hpb_generator/gen_messages.cc @@ -450,7 +450,7 @@ void WriteMessageImplementation( output( R"cc( ::hpb::Ptr $0::default_instance() { - return ::hpb::internal::CreateMessage<$0>( + return ::hpb::interop::upb::MakeCHandle<$0>( (upb_Message *)_$0_default_instance_.msg, _$0_default_instance_.arena); } diff --git a/hpb_generator/gen_repeated_fields.cc b/hpb_generator/gen_repeated_fields.cc index 7b6263a3cb..ca7f732e09 100644 --- a/hpb_generator/gen_repeated_fields.cc +++ b/hpb_generator/gen_repeated_fields.cc @@ -135,7 +135,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message, size_t len; auto* ptr = $3_$5(msg_, &len); assert(index < len); - return ::hpb::internal::CreateMessage<$4>( + return ::hpb::interop::upb::MakeCHandle<$4>( (upb_Message*)*(ptr + index), arena_); } )cc", diff --git a/protos/protos.h b/protos/protos.h index 70d2c03d7c..69849cacad 100644 --- a/protos/protos.h +++ b/protos/protos.h @@ -9,7 +9,6 @@ #include "google/protobuf/hpb/hpb.h" namespace protos { namespace internal { -using hpb::internal::CreateMessage; using hpb::internal::CreateMessageProxy; using hpb::internal::ExtensionIdentifier; using hpb::internal::GetArena; @@ -17,6 +16,10 @@ using hpb::internal::GetInternalMsg; using hpb::internal::PrivateAccess; using hpb::internal::Serialize; using hpb::internal::SetExtension; +template +typename T::CProxy CreateMessage(const upb_Message* msg, upb_Arena* arena) { + return hpb::interop::upb::MakeCHandle(msg, arena); +} } // namespace internal using hpb::Parse; using hpb::Serialize;