// Protocol Buffers - Google's data interchange format // Copyright 2024 Google LLC. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #ifndef GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__ #define GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__ // The sole public header in hpb/backend/upb #include #include "absl/strings/string_view.h" #include "google/protobuf/hpb/internal/internal.h" #include "google/protobuf/hpb/ptr.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/message.h" #include "upb/mini_table/message.h" namespace hpb::interop::upb { /** * Moves ownership of a message created in a source arena. * * Utility function to provide a way to move ownership across languages or VMs. * * Warning: any minitable skew will incur arbitrary memory access. Ensuring * minitable compatibility is the responsibility of the caller. */ // TODO: b/365824801 - consider rename to OwnMessage template T MoveMessage(upb_Message* msg, upb_Arena* arena) { return T(msg, arena); } template const upb_MiniTable* GetMiniTable(const T*) { return T::minitable(); } template const upb_MiniTable* GetMiniTable(Ptr) { return T::minitable(); } template auto* GetMessage(T&& message) { return hpb::internal::PrivateAccess::GetInternalMsg(std::forward(message)); } template upb_Arena* GetArena(Ptr message) { return hpb::internal::PrivateAccess::GetInternalArena(message); } template upb_Arena* GetArena(T* message) { return hpb::internal::PrivateAccess::GetInternalArena(message); } /** * 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. * * T must match actual type of `msg`. * TODO: b/361596328 - revisit GetArena for CHandles * TODO: b/362743843 - consider passing in MiniTable to ensure match */ template typename T::CProxy MakeCHandle(const upb_Message* msg, upb_Arena* arena) { return hpb::internal::PrivateAccess::CProxy(msg, arena); } /** * Creates a Handle to a mutable upb message. * * The supplied arena must outlive the hpb handle. * All messages reachable from from the upb message must * outlive the hpb handle. */ template typename T::Proxy MakeHandle(upb_Message* msg, upb_Arena* arena) { return typename T::Proxy(msg, arena); } /** * Creates a message in the given arena and returns a handle to it. * * The supplied arena must outlive the hpb handle. * All messages reachable from from the upb message must * outlive the hpb handle. */ template typename T::Proxy CreateMessage(upb_Arena* arena) { return hpb::internal::PrivateAccess::CreateMessage(arena); } inline absl::string_view FromUpbStringView(upb_StringView str) { return absl::string_view(str.data, str.size); } inline upb_StringView CopyToUpbStringView(absl::string_view str, upb_Arena* arena) { const size_t str_size = str.size(); char* buffer = static_cast(upb_Arena_Malloc(arena, str_size)); memcpy(buffer, str.data(), str_size); return upb_StringView_FromDataAndSize(buffer, str_size); } } // namespace hpb::interop::upb #endif // GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__