1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2024 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #ifndef GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__
9 #define GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__
10
11 // The sole public header in hpb/backend/upb
12
13 #include <cstring>
14
15 #include "absl/strings/string_view.h"
16 #include "google/protobuf/hpb/internal/internal.h"
17 #include "google/protobuf/hpb/ptr.h"
18 #include "upb/base/string_view.h"
19 #include "upb/mem/arena.h"
20 #include "upb/message/message.h"
21 #include "upb/mini_table/message.h"
22
23 namespace hpb::interop::upb {
24
25 /**
26 * Moves ownership of a message created in a source arena.
27 *
28 * Utility function to provide a way to move ownership across languages or VMs.
29 *
30 * Warning: any minitable skew will incur arbitrary memory access. Ensuring
31 * minitable compatibility is the responsibility of the caller.
32 */
33 // TODO: b/365824801 - consider rename to OwnMessage
34 template <typename T>
MoveMessage(upb_Message * msg,upb_Arena * arena)35 T MoveMessage(upb_Message* msg, upb_Arena* arena) {
36 return T(msg, arena);
37 }
38
39 template <typename T>
GetMiniTable(const T *)40 const upb_MiniTable* GetMiniTable(const T*) {
41 return T::minitable();
42 }
43
44 template <typename T>
GetMiniTable(Ptr<T>)45 const upb_MiniTable* GetMiniTable(Ptr<T>) {
46 return T::minitable();
47 }
48
49 template <typename T>
GetMessage(T && message)50 auto* GetMessage(T&& message) {
51 return hpb::internal::PrivateAccess::GetInternalMsg(std::forward<T>(message));
52 }
53
54 template <typename T>
GetArena(Ptr<T> message)55 upb_Arena* GetArena(Ptr<T> message) {
56 return hpb::internal::PrivateAccess::GetInternalArena(message);
57 }
58
59 template <typename T>
GetArena(T * message)60 upb_Arena* GetArena(T* message) {
61 return hpb::internal::PrivateAccess::GetInternalArena(message);
62 }
63
64 /**
65 * Creates a const Handle to a upb message.
66 *
67 * The supplied arena must outlive the hpb handle.
68 * All messages reachable from from the upb message must
69 * outlive the hpb handle.
70 *
71 * That is:
72 * upb allows message M on arena A to point to message M' on
73 * arena A'. As a user of hpb, you must guarantee that both A and A'
74 * outlive M and M'. In practice, this is enforced by using upb::Fuse,
75 * or manual tracking.
76 *
77 * The upb message must not be mutated directly while the handle is alive.
78 *
79 * T must match actual type of `msg`.
80 * TODO: b/361596328 - revisit GetArena for CHandles
81 * TODO: b/362743843 - consider passing in MiniTable to ensure match
82 */
83 template <typename T>
MakeCHandle(const upb_Message * msg,upb_Arena * arena)84 typename T::CProxy MakeCHandle(const upb_Message* msg, upb_Arena* arena) {
85 return hpb::internal::PrivateAccess::CProxy<T>(msg, arena);
86 }
87
88 /**
89 * Creates a Handle to a mutable upb message.
90 *
91 * The supplied arena must outlive the hpb handle.
92 * All messages reachable from from the upb message must
93 * outlive the hpb handle.
94 */
95 template <typename T>
MakeHandle(upb_Message * msg,upb_Arena * arena)96 typename T::Proxy MakeHandle(upb_Message* msg, upb_Arena* arena) {
97 return typename T::Proxy(msg, arena);
98 }
99
100 /**
101 * Creates a message in the given arena and returns a handle to it.
102 *
103 * The supplied arena must outlive the hpb handle.
104 * All messages reachable from from the upb message must
105 * outlive the hpb handle.
106 */
107 template <typename T>
CreateMessage(upb_Arena * arena)108 typename T::Proxy CreateMessage(upb_Arena* arena) {
109 return hpb::internal::PrivateAccess::CreateMessage<T>(arena);
110 }
111
FromUpbStringView(upb_StringView str)112 inline absl::string_view FromUpbStringView(upb_StringView str) {
113 return absl::string_view(str.data, str.size);
114 }
115
CopyToUpbStringView(absl::string_view str,upb_Arena * arena)116 inline upb_StringView CopyToUpbStringView(absl::string_view str,
117 upb_Arena* arena) {
118 const size_t str_size = str.size();
119 char* buffer = static_cast<char*>(upb_Arena_Malloc(arena, str_size));
120 memcpy(buffer, str.data(), str_size);
121 return upb_StringView_FromDataAndSize(buffer, str_size);
122 }
123
124 } // namespace hpb::interop::upb
125
126 #endif // GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__
127