blob: 6037b4426bda00573727bba87bba9d47c4e6a177 [file] [log] [blame]
Adam Cozzette501ecec2023-09-26 14:36:20 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
Adam Cozzette501ecec2023-09-26 14:36:20 -07003//
Protobuf Team Bot0fab7732023-11-20 13:38:15 -08004// 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
Adam Cozzette501ecec2023-09-26 14:36:20 -07007
8#ifndef UPB_PROTOS_PROTOS_H_
9#define UPB_PROTOS_PROTOS_H_
10
11#include <type_traits>
12#include <vector>
13
14#include "absl/status/status.h"
15#include "absl/status/statusor.h"
16#include "upb/base/status.hpp"
17#include "upb/mem/arena.hpp"
18#include "upb/message/copy.h"
Eric Salo21133d52023-11-27 18:40:50 -080019#include "upb/mini_table/extension.h"
Adam Cozzette501ecec2023-09-26 14:36:20 -070020#include "upb/wire/decode.h"
21#include "upb/wire/encode.h"
22
23namespace protos {
24
25using Arena = ::upb::Arena;
26class ExtensionRegistry;
27
28template <typename T>
29using Proxy = std::conditional_t<std::is_const<T>::value,
30 typename std::remove_const_t<T>::CProxy,
31 typename T::Proxy>;
32
33// Provides convenient access to Proxy and CProxy message types.
34//
35// Using rebinding and handling of const, Ptr<Message> and Ptr<const Message>
36// allows copying const with T* const and avoids using non-copyable Proxy types
37// directly.
38template <typename T>
39class Ptr final {
40 public:
41 Ptr() = delete;
42
43 // Implicit conversions
44 Ptr(T* m) : p_(m) {} // NOLINT
45 Ptr(const Proxy<T>* p) : p_(*p) {} // NOLINT
46 Ptr(Proxy<T> p) : p_(p) {} // NOLINT
47 Ptr(const Ptr& m) = default;
48
49 Ptr& operator=(Ptr v) & {
50 Proxy<T>::Rebind(p_, v.p_);
51 return *this;
52 }
53
54 Proxy<T> operator*() const { return p_; }
55 Proxy<T>* operator->() const {
56 return const_cast<Proxy<T>*>(std::addressof(p_));
57 }
58
59#ifdef __clang__
60#pragma clang diagnostic push
61#pragma clang diagnostic ignored "-Wclass-conversion"
62#endif
63 template <typename U = T, std::enable_if_t<!std::is_const<U>::value, int> = 0>
64 operator Ptr<const T>() const {
65 Proxy<const T> p(p_);
66 return Ptr<const T>(&p);
67 }
68#ifdef __clang__
69#pragma clang diagnostic pop
70#endif
71
72 private:
Eric Salob997cb62023-12-21 08:09:54 -080073 Ptr(upb_Message* msg, upb_Arena* arena) : p_(msg, arena) {} // NOLINT
Adam Cozzette501ecec2023-09-26 14:36:20 -070074
75 friend class Ptr<const T>;
76 friend typename T::Access;
77
78 Proxy<T> p_;
79};
80
81inline absl::string_view UpbStrToStringView(upb_StringView str) {
82 return absl::string_view(str.data, str.size);
83}
84
85// TODO: update bzl and move to upb runtime / protos.cc.
86inline upb_StringView UpbStrFromStringView(absl::string_view str,
87 upb_Arena* arena) {
88 const size_t str_size = str.size();
89 char* buffer = static_cast<char*>(upb_Arena_Malloc(arena, str_size));
90 memcpy(buffer, str.data(), str_size);
91 return upb_StringView_FromDataAndSize(buffer, str_size);
92}
93
94template <typename T>
95typename T::Proxy CreateMessage(::protos::Arena& arena) {
96 return typename T::Proxy(upb_Message_New(T::minitable(), arena.ptr()),
97 arena.ptr());
98}
99
100// begin:github_only
101// This type exists to work around an absl type that has not yet been
102// released.
103struct SourceLocation {
104 static SourceLocation current() { return {}; }
105 absl::string_view file_name() { return "<unknown>"; }
106 int line() { return 0; }
107};
108// end:github_only
109
110// begin:google_only
111// using SourceLocation = absl::SourceLocation;
112// end:google_only
113
114absl::Status MessageAllocationError(
115 SourceLocation loc = SourceLocation::current());
116
117absl::Status ExtensionNotFoundError(
118 int extension_number, SourceLocation loc = SourceLocation::current());
119
120absl::Status MessageDecodeError(upb_DecodeStatus status,
121 SourceLocation loc = SourceLocation::current());
122
123absl::Status MessageEncodeError(upb_EncodeStatus status,
124 SourceLocation loc = SourceLocation::current());
125
126namespace internal {
127struct PrivateAccess {
128 template <typename T>
129 static auto* GetInternalMsg(T&& message) {
130 return message->msg();
131 }
132 template <typename T>
Eric Salob997cb62023-12-21 08:09:54 -0800133 static auto Proxy(upb_Message* p, upb_Arena* arena) {
Adam Cozzette501ecec2023-09-26 14:36:20 -0700134 return typename T::Proxy(p, arena);
135 }
136 template <typename T>
Eric Salob997cb62023-12-21 08:09:54 -0800137 static auto CProxy(const upb_Message* p, upb_Arena* arena) {
Adam Cozzette501ecec2023-09-26 14:36:20 -0700138 return typename T::CProxy(p, arena);
139 }
Protobuf Team Botd9727cd2024-03-19 10:36:35 -0700140 template <typename T>
141 static auto CreateMessage(upb_Arena* arena) {
142 return typename T::Proxy(upb_Message_New(T::minitable(), arena), arena);
143 }
Adam Cozzette501ecec2023-09-26 14:36:20 -0700144};
145
146template <typename T>
147auto* GetInternalMsg(T&& message) {
148 return PrivateAccess::GetInternalMsg(std::forward<T>(message));
149}
150
151template <typename T>
152T CreateMessage() {
153 return T();
154}
155
156template <typename T>
Eric Salob997cb62023-12-21 08:09:54 -0800157typename T::Proxy CreateMessageProxy(upb_Message* msg, upb_Arena* arena) {
Adam Cozzette501ecec2023-09-26 14:36:20 -0700158 return typename T::Proxy(msg, arena);
159}
160
161template <typename T>
162typename T::CProxy CreateMessage(const upb_Message* msg, upb_Arena* arena) {
163 return PrivateAccess::CProxy<T>(msg, arena);
164}
165
166class ExtensionMiniTableProvider {
167 public:
168 constexpr explicit ExtensionMiniTableProvider(
169 const upb_MiniTableExtension* mini_table_ext)
170 : mini_table_ext_(mini_table_ext) {}
171 const upb_MiniTableExtension* mini_table_ext() const {
172 return mini_table_ext_;
173 }
174
175 private:
176 const upb_MiniTableExtension* mini_table_ext_;
177};
178
179// -------------------------------------------------------------------
180// ExtensionIdentifier
181// This is the type of actual extension objects. E.g. if you have:
182// extend Foo {
183// optional MyExtension bar = 1234;
184// }
185// then "bar" will be defined in C++ as:
186// ExtensionIdentifier<Foo, MyExtension> bar(&namespace_bar_ext);
187template <typename ExtendeeType, typename ExtensionType>
188class ExtensionIdentifier : public ExtensionMiniTableProvider {
189 public:
190 using Extension = ExtensionType;
191 using Extendee = ExtendeeType;
192
193 constexpr explicit ExtensionIdentifier(
194 const upb_MiniTableExtension* mini_table_ext)
195 : ExtensionMiniTableProvider(mini_table_ext) {}
196};
197
198template <typename T>
199upb_Arena* GetArena(Ptr<T> message) {
200 return static_cast<upb_Arena*>(message->GetInternalArena());
201}
202
203template <typename T>
204upb_Arena* GetArena(T* message) {
205 return static_cast<upb_Arena*>(message->GetInternalArena());
206}
207
208template <typename T>
209const upb_MiniTable* GetMiniTable(const T*) {
210 return T::minitable();
211}
212
213template <typename T>
214const upb_MiniTable* GetMiniTable(Ptr<T>) {
215 return T::minitable();
216}
217
218upb_ExtensionRegistry* GetUpbExtensions(
219 const ExtensionRegistry& extension_registry);
220
221absl::StatusOr<absl::string_view> Serialize(const upb_Message* message,
222 const upb_MiniTable* mini_table,
223 upb_Arena* arena, int options);
224
225bool HasExtensionOrUnknown(const upb_Message* msg,
226 const upb_MiniTableExtension* eid);
227
Eric Salof9af78e2024-01-22 21:18:26 -0800228bool GetOrPromoteExtension(upb_Message* msg, const upb_MiniTableExtension* eid,
229 upb_Arena* arena, upb_MessageValue* value);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700230
231void DeepCopy(upb_Message* target, const upb_Message* source,
232 const upb_MiniTable* mini_table, upb_Arena* arena);
233
234upb_Message* DeepClone(const upb_Message* source,
235 const upb_MiniTable* mini_table, upb_Arena* arena);
236
237absl::Status MoveExtension(upb_Message* message, upb_Arena* message_arena,
238 const upb_MiniTableExtension* ext,
239 upb_Message* extension, upb_Arena* extension_arena);
240
241absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena,
242 const upb_MiniTableExtension* ext,
243 const upb_Message* extension);
244
Hong Shinb57c3742024-06-04 10:24:56 -0700245template <typename T>
246struct RemovePtr;
247
248template <typename T>
249struct RemovePtr<Ptr<T>> {
250 using type = T;
251};
252
253template <typename T>
254struct RemovePtr<T*> {
255 using type = T;
256};
257
258template <typename T>
259using RemovePtrT = typename RemovePtr<T>::type;
260
261template <typename T, typename U = RemovePtrT<T>,
262 typename = std::enable_if_t<!std::is_const_v<U>>>
263using PtrOrRaw = T;
264
Adam Cozzette501ecec2023-09-26 14:36:20 -0700265} // namespace internal
266
267template <typename T>
268void DeepCopy(Ptr<const T> source_message, Ptr<T> target_message) {
269 static_assert(!std::is_const_v<T>);
270 ::protos::internal::DeepCopy(
271 internal::GetInternalMsg(target_message),
272 internal::GetInternalMsg(source_message), T::minitable(),
273 static_cast<upb_Arena*>(target_message->GetInternalArena()));
274}
275
276template <typename T>
277typename T::Proxy CloneMessage(Ptr<T> message, upb_Arena* arena) {
278 return internal::PrivateAccess::Proxy<T>(
279 ::protos::internal::DeepClone(internal::GetInternalMsg(message),
280 T::minitable(), arena),
281 arena);
282}
283
284template <typename T>
285void DeepCopy(Ptr<const T> source_message, T* target_message) {
286 static_assert(!std::is_const_v<T>);
287 DeepCopy(source_message, protos::Ptr(target_message));
288}
289
290template <typename T>
291void DeepCopy(const T* source_message, Ptr<T> target_message) {
292 static_assert(!std::is_const_v<T>);
293 DeepCopy(protos::Ptr(source_message), target_message);
294}
295
296template <typename T>
297void DeepCopy(const T* source_message, T* target_message) {
298 static_assert(!std::is_const_v<T>);
299 DeepCopy(protos::Ptr(source_message), protos::Ptr(target_message));
300}
301
302template <typename T>
Hong Shinb57c3742024-06-04 10:24:56 -0700303void ClearMessage(internal::PtrOrRaw<T> message) {
304 auto ptr = Ptr(message);
305 auto minitable = internal::GetMiniTable(ptr);
306 upb_Message_Clear(internal::GetInternalMsg(ptr), minitable);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700307}
308
309class ExtensionRegistry {
310 public:
311 ExtensionRegistry(
312 const std::vector<const ::protos::internal::ExtensionMiniTableProvider*>&
313 extensions,
314 const upb::Arena& arena)
315 : registry_(upb_ExtensionRegistry_New(arena.ptr())) {
316 if (registry_) {
317 for (const auto& ext_provider : extensions) {
318 const auto* ext = ext_provider->mini_table_ext();
319 bool success = upb_ExtensionRegistry_AddArray(registry_, &ext, 1);
320 if (!success) {
321 registry_ = nullptr;
322 break;
323 }
324 }
325 }
326 }
327
328 private:
329 friend upb_ExtensionRegistry* ::protos::internal::GetUpbExtensions(
330 const ExtensionRegistry& extension_registry);
331 upb_ExtensionRegistry* registry_;
332};
333
334template <typename T>
335using EnableIfProtosClass = std::enable_if_t<
336 std::is_base_of<typename T::Access, T>::value &&
337 std::is_base_of<typename T::Access, typename T::ExtendableType>::value>;
338
339template <typename T>
340using EnableIfMutableProto = std::enable_if_t<!std::is_const<T>::value>;
341
342template <typename T, typename Extendee, typename Extension,
343 typename = EnableIfProtosClass<T>>
344ABSL_MUST_USE_RESULT bool HasExtension(
345 Ptr<T> message,
346 const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) {
347 return ::protos::internal::HasExtensionOrUnknown(
348 ::protos::internal::GetInternalMsg(message), id.mini_table_ext());
349}
350
351template <typename T, typename Extendee, typename Extension,
352 typename = EnableIfProtosClass<T>>
353ABSL_MUST_USE_RESULT bool HasExtension(
354 const T* message,
355 const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) {
356 return HasExtension(protos::Ptr(message), id);
357}
358
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700359template <typename T, typename Extension, typename = EnableIfProtosClass<T>,
360 typename = EnableIfMutableProto<T>>
Adam Cozzette501ecec2023-09-26 14:36:20 -0700361void ClearExtension(
362 Ptr<T> message,
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700363 const ::protos::internal::ExtensionIdentifier<T, Extension>& id) {
Adam Cozzette501ecec2023-09-26 14:36:20 -0700364 static_assert(!std::is_const_v<T>, "");
Eric Saloc02f9432024-01-08 07:34:09 -0800365 upb_Message_ClearExtension(internal::GetInternalMsg(message),
366 id.mini_table_ext());
Adam Cozzette501ecec2023-09-26 14:36:20 -0700367}
368
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700369template <typename T, typename Extension, typename = EnableIfProtosClass<T>>
Adam Cozzette501ecec2023-09-26 14:36:20 -0700370void ClearExtension(
371 T* message,
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700372 const ::protos::internal::ExtensionIdentifier<T, Extension>& id) {
Adam Cozzette501ecec2023-09-26 14:36:20 -0700373 ClearExtension(::protos::Ptr(message), id);
374}
375
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700376template <typename T, typename Extension, typename = EnableIfProtosClass<T>,
377 typename = EnableIfMutableProto<T>>
Adam Cozzette501ecec2023-09-26 14:36:20 -0700378absl::Status SetExtension(
379 Ptr<T> message,
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700380 const ::protos::internal::ExtensionIdentifier<T, Extension>& id,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700381 const Extension& value) {
382 static_assert(!std::is_const_v<T>);
383 auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena());
384 return ::protos::internal::SetExtension(internal::GetInternalMsg(message),
385 message_arena, id.mini_table_ext(),
386 internal::GetInternalMsg(&value));
387}
388
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700389template <typename T, typename Extension, typename = EnableIfProtosClass<T>,
390 typename = EnableIfMutableProto<T>>
Adam Cozzette501ecec2023-09-26 14:36:20 -0700391absl::Status SetExtension(
392 Ptr<T> message,
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700393 const ::protos::internal::ExtensionIdentifier<T, Extension>& id,
394 Ptr<Extension> value) {
395 static_assert(!std::is_const_v<T>);
396 auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena());
397 return ::protos::internal::SetExtension(internal::GetInternalMsg(message),
398 message_arena, id.mini_table_ext(),
399 internal::GetInternalMsg(value));
400}
401
402template <typename T, typename Extension, typename = EnableIfProtosClass<T>,
403 typename = EnableIfMutableProto<T>>
404absl::Status SetExtension(
405 Ptr<T> message,
406 const ::protos::internal::ExtensionIdentifier<T, Extension>& id,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700407 Extension&& value) {
408 Extension ext = std::move(value);
409 static_assert(!std::is_const_v<T>);
410 auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena());
411 auto* extension_arena = static_cast<upb_Arena*>(ext.GetInternalArena());
412 return ::protos::internal::MoveExtension(
413 internal::GetInternalMsg(message), message_arena, id.mini_table_ext(),
414 internal::GetInternalMsg(&ext), extension_arena);
415}
416
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700417template <typename T, typename Extension, typename = EnableIfProtosClass<T>>
Adam Cozzette501ecec2023-09-26 14:36:20 -0700418absl::Status SetExtension(
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700419 T* message, const ::protos::internal::ExtensionIdentifier<T, Extension>& id,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700420 const Extension& value) {
421 return ::protos::SetExtension(::protos::Ptr(message), id, value);
422}
423
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700424template <typename T, typename Extension, typename = EnableIfProtosClass<T>>
Adam Cozzette501ecec2023-09-26 14:36:20 -0700425absl::Status SetExtension(
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700426 T* message, const ::protos::internal::ExtensionIdentifier<T, Extension>& id,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700427 Extension&& value) {
428 return ::protos::SetExtension(::protos::Ptr(message), id,
429 std::forward<Extension>(value));
430}
431
Protobuf Team Bot396d6612024-05-14 11:12:50 -0700432template <typename T, typename Extension, typename = EnableIfProtosClass<T>>
433absl::Status SetExtension(
434 T* message, const ::protos::internal::ExtensionIdentifier<T, Extension>& id,
435 Ptr<Extension> value) {
436 return ::protos::SetExtension(::protos::Ptr(message), id, value);
437}
438
Adam Cozzette501ecec2023-09-26 14:36:20 -0700439template <typename T, typename Extendee, typename Extension,
440 typename = EnableIfProtosClass<T>>
441absl::StatusOr<Ptr<const Extension>> GetExtension(
442 Ptr<T> message,
443 const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) {
444 // TODO: Fix const correctness issues.
Eric Salof9af78e2024-01-22 21:18:26 -0800445 upb_MessageValue value;
446 const bool ok = ::protos::internal::GetOrPromoteExtension(
Adam Cozzette501ecec2023-09-26 14:36:20 -0700447 const_cast<upb_Message*>(internal::GetInternalMsg(message)),
Eric Salof9af78e2024-01-22 21:18:26 -0800448 id.mini_table_ext(), ::protos::internal::GetArena(message), &value);
449 if (!ok) {
Eric Salo21133d52023-11-27 18:40:50 -0800450 return ExtensionNotFoundError(
451 upb_MiniTableExtension_Number(id.mini_table_ext()));
Adam Cozzette501ecec2023-09-26 14:36:20 -0700452 }
453 return Ptr<const Extension>(::protos::internal::CreateMessage<Extension>(
Eric Salof9af78e2024-01-22 21:18:26 -0800454 (upb_Message*)value.msg_val, ::protos::internal::GetArena(message)));
Adam Cozzette501ecec2023-09-26 14:36:20 -0700455}
456
457template <typename T, typename Extendee, typename Extension,
458 typename = EnableIfProtosClass<T>>
459absl::StatusOr<Ptr<const Extension>> GetExtension(
460 const T* message,
461 const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) {
462 return GetExtension(protos::Ptr(message), id);
463}
464
Adam Cozzette501ecec2023-09-26 14:36:20 -0700465template <typename T>
466ABSL_MUST_USE_RESULT bool Parse(Ptr<T> message, absl::string_view bytes) {
467 static_assert(!std::is_const_v<T>);
468 upb_Message_Clear(internal::GetInternalMsg(message),
469 ::protos::internal::GetMiniTable(message));
470 auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
471 return upb_Decode(bytes.data(), bytes.size(),
472 internal::GetInternalMsg(message),
473 ::protos::internal::GetMiniTable(message),
474 /* extreg= */ nullptr, /* options= */ 0,
475 arena) == kUpb_DecodeStatus_Ok;
476}
477
478template <typename T>
479ABSL_MUST_USE_RESULT bool Parse(
480 Ptr<T> message, absl::string_view bytes,
481 const ::protos::ExtensionRegistry& extension_registry) {
482 static_assert(!std::is_const_v<T>);
483 upb_Message_Clear(internal::GetInternalMsg(message),
484 ::protos::internal::GetMiniTable(message));
485 auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
486 return upb_Decode(bytes.data(), bytes.size(),
487 internal::GetInternalMsg(message),
488 ::protos::internal::GetMiniTable(message),
489 /* extreg= */
490 ::protos::internal::GetUpbExtensions(extension_registry),
491 /* options= */ 0, arena) == kUpb_DecodeStatus_Ok;
492}
493
494template <typename T>
495ABSL_MUST_USE_RESULT bool Parse(
496 T* message, absl::string_view bytes,
497 const ::protos::ExtensionRegistry& extension_registry) {
498 static_assert(!std::is_const_v<T>);
499 return Parse(protos::Ptr(message, bytes, extension_registry));
500}
501
502template <typename T>
503ABSL_MUST_USE_RESULT bool Parse(T* message, absl::string_view bytes) {
504 static_assert(!std::is_const_v<T>);
505 upb_Message_Clear(internal::GetInternalMsg(message),
506 ::protos::internal::GetMiniTable(message));
507 auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
508 return upb_Decode(bytes.data(), bytes.size(),
509 internal::GetInternalMsg(message),
510 ::protos::internal::GetMiniTable(message),
511 /* extreg= */ nullptr, /* options= */ 0,
512 arena) == kUpb_DecodeStatus_Ok;
513}
514
515template <typename T>
516absl::StatusOr<T> Parse(absl::string_view bytes, int options = 0) {
517 T message;
518 auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
519 upb_DecodeStatus status =
520 upb_Decode(bytes.data(), bytes.size(), message.msg(),
521 ::protos::internal::GetMiniTable(&message),
522 /* extreg= */ nullptr, /* options= */ 0, arena);
523 if (status == kUpb_DecodeStatus_Ok) {
524 return message;
525 }
526 return MessageDecodeError(status);
527}
528
529template <typename T>
530absl::StatusOr<T> Parse(absl::string_view bytes,
531 const ::protos::ExtensionRegistry& extension_registry,
532 int options = 0) {
533 T message;
534 auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
535 upb_DecodeStatus status =
536 upb_Decode(bytes.data(), bytes.size(), message.msg(),
537 ::protos::internal::GetMiniTable(&message),
538 ::protos::internal::GetUpbExtensions(extension_registry),
539 /* options= */ 0, arena);
540 if (status == kUpb_DecodeStatus_Ok) {
541 return message;
542 }
543 return MessageDecodeError(status);
544}
545
546template <typename T>
547absl::StatusOr<absl::string_view> Serialize(const T* message, upb::Arena& arena,
548 int options = 0) {
549 return ::protos::internal::Serialize(
550 internal::GetInternalMsg(message),
551 ::protos::internal::GetMiniTable(message), arena.ptr(), options);
552}
553
554template <typename T>
555absl::StatusOr<absl::string_view> Serialize(Ptr<T> message, upb::Arena& arena,
556 int options = 0) {
557 return ::protos::internal::Serialize(
558 internal::GetInternalMsg(message),
559 ::protos::internal::GetMiniTable(message), arena.ptr(), options);
560}
561
562} // namespace protos
563
564#endif // UPB_PROTOS_PROTOS_H_