VLink 2.0.0
A high-performance communication middleware
载入中...
搜索中...
未找到
flatbuffers_registry.h
浏览该文件的文档.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file flatbuffers_registry.h
26 * @brief Process-local registry for BFBS blobs compiled into the current library.
27 *
28 * @details
29 * Protobuf already provides @c google::protobuf::DescriptorPool::generated_pool()
30 * as the global registry of generated descriptors. FlatBuffers has no equivalent
31 * runtime pool for BFBS reflection data, so VLink keeps a small process-local
32 * registry that stores BFBS blobs embedded into the current binary/library.
33 *
34 * The registry is intentionally limited to:
35 * - registering compiled-in BFBS blobs
36 * - looking up one schema by fully-qualified root type
37 * - enumerating all registered BFBS schemas
38 *
39 * It does not read schema files from disk and does not depend on
40 * @c VLINK_PROTO_DIR / @c VLINK_FBS_DIR.
41 */
42
43#pragma once
44
45#include <cstddef>
46#include <mutex>
47#include <shared_mutex>
48#include <string>
49#include <unordered_map>
50#include <vector>
51
52#include "../impl/types.h"
53
54#if __has_include(<flatbuffers/idl.h>)
55#include <flatbuffers/flatbuffers.h>
56#include <flatbuffers/idl.h>
57#define VLINK_HAS_SCHEMA_PLUGIN_FLATBUFFERS
58#endif
59
60#ifdef VLINK_HAS_SCHEMA_PLUGIN_FLATBUFFERS
61
62namespace vlink {
63
64/**
65 * @class FlatbuffersRegistry
66 * @brief Global BFBS registry shared by schema-plugin instances in one process.
67 *
68 * @details
69 * The registry owns copied BFBS blobs so callers may register data from
70 * generated @c *BinarySchema helpers without managing the lifetime manually.
71 * Each BFBS blob is keyed by its fully-qualified FlatBuffers root type name.
72 */
73class FlatbuffersRegistry final {
74 public:
75 /**
76 * @brief Registers one BFBS blob from a generated @c *BinarySchema helper type.
77 *
78 * @tparam BinarySchema Generated type exposing @c data() and @c size().
79 * @param name Fully-qualified FlatBuffers root type name.
80 * @return @c true if the BFBS blob is valid and was inserted successfully.
81 */
82 template <typename BinarySchema>
83 static bool register_schema(const std::string& name);
84
85 /**
86 * @brief Registers one BFBS blob into the global registry.
87 *
88 * @param name Fully-qualified FlatBuffers root type name.
89 * @param bfbs_data Pointer to BFBS bytes.
90 * @param bfbs_size Size of @p bfbs_data.
91 * @return @c true if the BFBS blob is valid and was inserted successfully.
92 */
93 static bool register_schema(const std::string& name, const uint8_t* bfbs_data, size_t bfbs_size);
94
95 /**
96 * @brief Finds one registered BFBS schema by root type name.
97 *
98 * @param name Fully-qualified FlatBuffers root type name.
99 * @return Copy of the registered @c SchemaData, or an empty schema when absent.
100 */
101 [[nodiscard]] SchemaData search_schema(const std::string& name);
102
103 /**
104 * @brief Returns all BFBS schemas currently registered in this process.
105 *
106 * @return Vector of registered FlatBuffers schema blobs.
107 */
108 [[nodiscard]] std::vector<SchemaData> get_all_schemas();
109
110 private:
111 FlatbuffersRegistry() = default;
112
113 ~FlatbuffersRegistry() = default;
114
115 static SchemaData build_data(const std::string& name, const uint8_t* bfbs_data, size_t bfbs_size);
116
117 std::unordered_map<std::string, SchemaData> map_;
118 std::shared_mutex mtx_;
119
120 VLINK_SINGLETON_DECLARE(FlatbuffersRegistry)
121};
122
123////////////////////////////////////////////////////////////////
124// Details
125////////////////////////////////////////////////////////////////
126
127template <typename BinarySchema>
128inline bool FlatbuffersRegistry::register_schema(const std::string& name) {
129 return register_schema(name, BinarySchema::data(), BinarySchema::size());
130}
131
132inline bool FlatbuffersRegistry::register_schema(const std::string& name, const uint8_t* bfbs_data, size_t bfbs_size) {
133 auto schema = build_data(name, bfbs_data, bfbs_size);
134
135 if VUNLIKELY (schema.encoding != "flatbuffers" || schema.data.empty()) {
136 return false;
137 }
138
139 auto& registry = get();
140
141 std::lock_guard lock(registry.mtx_);
142 registry.map_[schema.name] = std::move(schema);
143
144 return true;
145}
146
147inline SchemaData FlatbuffersRegistry::search_schema(const std::string& name) {
148 std::shared_lock lock(mtx_);
149
150 auto iter = map_.find(name);
151
152 if (iter == map_.end()) {
153 return {};
154 }
155
156 return iter->second;
157}
158
159inline std::vector<SchemaData> FlatbuffersRegistry::get_all_schemas() {
160 std::shared_lock lock(mtx_);
161
162 std::vector<SchemaData> schemas;
163 schemas.reserve(map_.size());
164
165 for (const auto& [name, schema] : map_) {
166 (void)name;
167 schemas.emplace_back(schema);
168 }
169
170 return schemas;
171}
172
173inline SchemaData FlatbuffersRegistry::build_data(const std::string& name, const uint8_t* bfbs_data, size_t bfbs_size) {
174 SchemaData schema;
176
177 if VUNLIKELY (name.empty() || bfbs_data == nullptr || bfbs_size == 0) {
178 return schema;
179 }
180
181 schema.name = name;
182 schema.encoding = "flatbuffers";
183 schema.schema_type = SchemaType::kFlatbuffers;
184 schema.data = Bytes::shallow_copy(bfbs_data, bfbs_size);
185
186 flatbuffers::Verifier verifier(schema.data.data(), schema.data.size());
187
188 if VUNLIKELY (!reflection::VerifySchemaBuffer(verifier)) {
189 schema.encoding.clear();
190 schema.schema_type = SchemaType::kUnknown;
191 schema.data.clear();
192 }
193
194 return schema;
195}
196
197} // namespace vlink
198
199/**
200 * @def VLINK_REGISTER_FLATBUFFERS_NOW(schema_name, binary_schema_type)
201 * @brief Immediately registers a compiled FlatBuffers BFBS schema.
202 *
203 * @details
204 * Expands to a direct call to
205 * ::vlink::FlatbuffersRegistry::register_schema<binary_schema_type>().
206 * Registration is performed immediately at the point of expansion —
207 * no static objects are created, and no automatic initialization is involved.
208 */
209#define VLINK_REGISTER_FLATBUFFERS_NOW(schema_name, binary_schema_type) \
210 ::vlink::FlatbuffersRegistry::register_schema<binary_schema_type>(schema_name)
211
212/**
213 * @def VLINK_REGISTER_FLATBUFFERS(schema_name, binary_schema_type)
214 * @brief Automatically registers an embedded FlatBuffers BFBS schema
215 * during static initialization.
216 *
217 * @details
218 * Defines one translation-unit-local helper type and one translation-unit-local
219 * static object whose constructor registers the schema. The helper names are
220 * made unique for every expansion, so the macro may be used multiple times in
221 * the same translation unit and still works for namespaced or templated
222 * @p binary_schema_type values.
223 *
224 * Example:
225 * @code
226 * VLINK_REGISTER_FLATBUFFERS("Helloworld.fbs.User",
227 * Helloworld::fbs::UserBinarySchema);
228 * @endcode
229 */
230#define VLINK_REGISTER_FLATBUFFERS(schema_name, binary_schema_type) \
231 /* NOLINTBEGIN */ \
232 namespace { \
233 template <int Id> \
234 struct VlinkAutoRegisterFlatbuffersHelper; \
235 \
236 template <> \
237 struct VlinkAutoRegisterFlatbuffersHelper<__COUNTER__> { \
238 struct Init { \
239 Init() noexcept { \
240 using SchemaType = binary_schema_type; \
241 (void)VLINK_REGISTER_FLATBUFFERS_NOW(schema_name, SchemaType); \
242 } \
243 }; \
244 \
245 [[maybe_unused]] inline static const Init instance{}; \
246 }; \
247 } \
248 /* NOLINTEND */
249
250#endif // VLINK_REGISTER_FLATBUFFERS_MACROS_INCLUDED
#define VUNLIKELY(...)
Shorthand alias for VLINK_UNLIKELY. Hints that the expression is unlikely true.
定义 macros.h:302
#define VLINK_SINGLETON_DECLARE(classname)
Declares a complete Meyer's-singleton get() method with safety guards.
定义 macros.h:244
Core type definitions shared across all VLink node implementations.