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_EXTENSION_H__ 9 #define GOOGLE_PROTOBUF_HPB_EXTENSION_H__ 10 11 #include <cstdint> 12 #include <vector> 13 14 #include "upb/mem/arena.hpp" 15 #include "upb/mini_table/extension.h" 16 #include "upb/mini_table/extension_registry.h" 17 18 namespace hpb { 19 class ExtensionRegistry; 20 21 namespace internal { 22 23 class ExtensionMiniTableProvider { 24 public: ExtensionMiniTableProvider(const upb_MiniTableExtension * mini_table_ext)25 constexpr explicit ExtensionMiniTableProvider( 26 const upb_MiniTableExtension* mini_table_ext) 27 : mini_table_ext_(mini_table_ext) {} mini_table_ext()28 const upb_MiniTableExtension* mini_table_ext() const { 29 return mini_table_ext_; 30 } 31 32 private: 33 const upb_MiniTableExtension* mini_table_ext_; 34 }; 35 36 // ------------------------------------------------------------------- 37 // ExtensionIdentifier 38 // This is the type of actual extension objects. E.g. if you have: 39 // extend Foo { 40 // optional MyExtension bar = 1234; 41 // } 42 // then "bar" will be defined in C++ as: 43 // ExtensionIdentifier<Foo, MyExtension> bar(&namespace_bar_ext); 44 template <typename ExtendeeType, typename ExtensionType> 45 class ExtensionIdentifier : public ExtensionMiniTableProvider { 46 public: 47 using Extension = ExtensionType; 48 using Extendee = ExtendeeType; 49 ExtensionIdentifier(const upb_MiniTableExtension * mini_table_ext)50 constexpr explicit ExtensionIdentifier( 51 const upb_MiniTableExtension* mini_table_ext) 52 : ExtensionMiniTableProvider(mini_table_ext) {} 53 54 private: number()55 constexpr uint32_t number() const { 56 return upb_MiniTableExtension_Number(mini_table_ext()); 57 } 58 friend struct PrivateAccess; 59 }; 60 61 upb_ExtensionRegistry* GetUpbExtensions( 62 const ExtensionRegistry& extension_registry); 63 64 } // namespace internal 65 66 class ExtensionRegistry { 67 public: ExtensionRegistry(const std::vector<const internal::ExtensionMiniTableProvider * > & extensions,const upb::Arena & arena)68 ExtensionRegistry( 69 const std::vector<const internal::ExtensionMiniTableProvider*>& 70 extensions, 71 const upb::Arena& arena) 72 : registry_(upb_ExtensionRegistry_New(arena.ptr())) { 73 if (registry_) { 74 for (const auto& ext_provider : extensions) { 75 const auto* ext = ext_provider->mini_table_ext(); 76 bool success = upb_ExtensionRegistry_AddArray(registry_, &ext, 1); 77 if (!success) { 78 registry_ = nullptr; 79 break; 80 } 81 } 82 } 83 } 84 85 private: 86 friend upb_ExtensionRegistry* ::hpb::internal::GetUpbExtensions( 87 const ExtensionRegistry& extension_registry); 88 upb_ExtensionRegistry* registry_; 89 }; 90 } // namespace hpb 91 92 #endif // GOOGLE_PROTOBUF_HPB_EXTENSION_H__ 93