// 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_EXTENSION_H__ #define GOOGLE_PROTOBUF_HPB_EXTENSION_H__ #include #include #include "absl/base/attributes.h" #include "google/protobuf/hpb/backend/upb/interop.h" #include "google/protobuf/hpb/internal/message_lock.h" #include "google/protobuf/hpb/internal/template_help.h" #include "google/protobuf/hpb/ptr.h" #include "upb/mem/arena.hpp" #include "upb/mini_table/extension.h" #include "upb/mini_table/extension_registry.h" namespace hpb { class ExtensionRegistry; namespace internal { class ExtensionMiniTableProvider { public: constexpr explicit ExtensionMiniTableProvider( const upb_MiniTableExtension* mini_table_ext) : mini_table_ext_(mini_table_ext) {} const upb_MiniTableExtension* mini_table_ext() const { return mini_table_ext_; } private: const upb_MiniTableExtension* mini_table_ext_; }; // ------------------------------------------------------------------- // ExtensionIdentifier // This is the type of actual extension objects. E.g. if you have: // extend Foo { // optional MyExtension bar = 1234; // } // then "bar" will be defined in C++ as: // ExtensionIdentifier bar(&namespace_bar_ext); template class ExtensionIdentifier : public ExtensionMiniTableProvider { public: using Extension = ExtensionType; using Extendee = ExtendeeType; constexpr explicit ExtensionIdentifier( const upb_MiniTableExtension* mini_table_ext) : ExtensionMiniTableProvider(mini_table_ext) {} private: constexpr uint32_t number() const { return upb_MiniTableExtension_Number(mini_table_ext()); } friend struct PrivateAccess; }; upb_ExtensionRegistry* GetUpbExtensions( const ExtensionRegistry& extension_registry); } // namespace internal class ExtensionRegistry { public: ExtensionRegistry( const std::vector& extensions, const upb::Arena& arena) : registry_(upb_ExtensionRegistry_New(arena.ptr())) { if (registry_) { for (const auto& ext_provider : extensions) { const auto* ext = ext_provider->mini_table_ext(); bool success = upb_ExtensionRegistry_AddArray(registry_, &ext, 1); if (!success) { registry_ = nullptr; break; } } } } private: friend upb_ExtensionRegistry* ::hpb::internal::GetUpbExtensions( const ExtensionRegistry& extension_registry); upb_ExtensionRegistry* registry_; }; template > ABSL_MUST_USE_RESULT bool HasExtension( Ptr message, const ::hpb::internal::ExtensionIdentifier& id) { return ::hpb::internal::HasExtensionOrUnknown( hpb::interop::upb::GetMessage(message), id.mini_table_ext()); } template > ABSL_MUST_USE_RESULT bool HasExtension( const T* message, const ::hpb::internal::ExtensionIdentifier& id) { return HasExtension(Ptr(message), id); } template , typename = hpb::internal::EnableIfMutableProto> void ClearExtension( Ptr message, const ::hpb::internal::ExtensionIdentifier& id) { static_assert(!std::is_const_v, ""); upb_Message_ClearExtension(hpb::interop::upb::GetMessage(message), id.mini_table_ext()); } template > void ClearExtension( T* message, const ::hpb::internal::ExtensionIdentifier& id) { ClearExtension(Ptr(message), id); } } // namespace hpb #endif // GOOGLE_PROTOBUF_HPB_EXTENSION_H__