|
|
|
// 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 <cstring>
|
|
|
|
|
|
|
|
#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 <typename T>
|
|
|
|
T MoveMessage(upb_Message* msg, upb_Arena* arena) {
|
|
|
|
return T(msg, arena);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
const upb_MiniTable* GetMiniTable(const T*) {
|
|
|
|
return T::minitable();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
const upb_MiniTable* GetMiniTable(Ptr<T>) {
|
|
|
|
return T::minitable();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
auto* GetMessage(T&& message) {
|
|
|
|
return hpb::internal::PrivateAccess::GetInternalMsg(std::forward<T>(message));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
upb_Arena* GetArena(Ptr<T> message) {
|
|
|
|
return hpb::internal::PrivateAccess::GetInternalArena(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
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>
|
|
|
|
typename T::CProxy MakeCHandle(const upb_Message* msg, upb_Arena* arena) {
|
|
|
|
return hpb::internal::PrivateAccess::CProxy<T>(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>
|
|
|
|
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>
|
|
|
|
typename T::Proxy CreateMessage(upb_Arena* arena) {
|
|
|
|
return hpb::internal::PrivateAccess::CreateMessage<T>(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<char*>(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__
|