• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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