24#ifndef FieldCodecManager20110405H
25#define FieldCodecManager20110405H
29#include "field_codec.h"
30#include "internal/field_codec_data.h"
31#include "internal/type_helper.h"
33#include "thread_safety.h"
54 template <
class Codec>
55 typename std::enable_if<
56 std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
57 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value,
59 add(
const std::string& name);
66 template <
class Codec>
67 typename std::enable_if<
68 !(std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
69 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value),
71 add(
const std::string& name);
78 template <
class Codec, google::protobuf::FieldDescriptor::Type type>
79 void add(
const std::string& name);
86 template <
class Codec>
87 typename std::enable_if<
88 std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
89 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value,
91 remove(
const std::string& name);
98 template <
class Codec>
99 typename std::enable_if<
100 !(std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
101 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value),
110 template <
class Codec, google::protobuf::FieldDescriptor::Type type>
111 void remove(
const std::string& name);
114 std::shared_ptr<FieldCodecBase>
find(
const google::protobuf::FieldDescriptor* field,
115 int codec_version,
bool has_codec_group,
116 const std::string& codec_group)
const
118 std::string name = __find_codec(field, has_codec_group, codec_group);
120 if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
121 return find(field->message_type(), codec_version, name);
123 return __find(field->type(), codec_version, name,
"");
130 std::shared_ptr<FieldCodecBase>
find(
const google::protobuf::Descriptor* desc,
131 int codec_version = 0, std::string name =
"")
const
137 if (desc->options().GetExtension(dccl::msg).has_codec())
138 name = desc->options().GetExtension(dccl::msg).codec();
140 name = FieldCodecBase::codec_group(desc);
141 codec_version = desc->options().GetExtension(dccl::msg).codec_version();
144 return __find(google::protobuf::FieldDescriptor::TYPE_MESSAGE, codec_version, name,
145 std::string(desc->full_name()));
148 std::shared_ptr<FieldCodecBase>
find(google::protobuf::FieldDescriptor::Type type,
149 int codec_version, std::string name)
const
151 return __find(type, codec_version, name,
"");
156 type_helper_.reset();
160 internal::TypeHelper& type_helper() {
return type_helper_; }
161 const internal::TypeHelper& type_helper()
const {
return type_helper_; }
163 internal::CodecData& codec_data() {
return codec_data_; }
164 const internal::CodecData& codec_data()
const {
return codec_data_; }
166 void set_hash(
const google::protobuf::Descriptor* desc, std::size_t hash)
168 hashes_[desc] = hash;
170 bool has_hash(
const google::protobuf::Descriptor* desc)
const {
return hashes_.count(desc); }
171 std::size_t hash(
const google::protobuf::Descriptor* desc)
const {
return hashes_.at(desc); }
174 std::shared_ptr<FieldCodecBase> __find(google::protobuf::FieldDescriptor::Type type,
175 int codec_version,
const std::string& codec_name,
176 const std::string& type_name)
const;
178 std::string __mangle_name(
const std::string& codec_name,
const std::string& type_name)
const
180 return type_name.empty() ? codec_name : codec_name +
"[" + type_name +
"]";
183 template <
typename WireType,
typename FieldType,
class Codec>
184 void add_all_types(
const std::string& name);
186 template <
class Codec>
187 void add_single_type(
const std::string& name,
188 google::protobuf::FieldDescriptor::Type field_type,
189 google::protobuf::FieldDescriptor::CppType wire_type);
191 void add_single_type(std::shared_ptr<FieldCodecBase> new_field_codec,
const std::string& name,
192 google::protobuf::FieldDescriptor::Type field_type,
193 google::protobuf::FieldDescriptor::CppType wire_type);
195 template <
typename WireType,
typename FieldType,
class Codec>
196 void remove_all_types(
const std::string& name);
198 template <
class Codec>
199 void remove_single_type(
const std::string& name,
200 google::protobuf::FieldDescriptor::Type field_type,
201 google::protobuf::FieldDescriptor::CppType wire_type);
203 std::string __find_codec(
const google::protobuf::FieldDescriptor* field,
bool has_codec_group,
204 const std::string& codec_group)
const
209 if (dccl_field_options.has_codec())
210 return dccl_field_options.codec();
212 else if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
213 field->message_type()->options().GetExtension(dccl::msg).has_codec())
214 return field->message_type()->options().GetExtension(dccl::msg).codec();
216 else if (has_codec_group)
220 return dccl_field_options.codec();
223 void check_deprecated(
const std::string& name)
const;
226 using InsideMap = std::map<std::string, std::shared_ptr<FieldCodecBase>>;
227 std::map<google::protobuf::FieldDescriptor::Type, InsideMap> codecs_;
229 internal::TypeHelper type_helper_;
230 internal::CodecData codec_data_;
232 std::map<const google::protobuf::Descriptor*, std::size_t> hashes_;
233 std::map<std::string, std::string> deprecated_names_;
239 template <
class Codec>
240 typename std::enable_if<
241 std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
242 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value,
244 add(
const std::string& )
246 static_assert(
sizeof(
Codec) == 0,
247 "The global `FieldCodecManager::add<...>(...)` is no longer available. Use "
248 "`dccl::Codec codec; codec.manager().add<...>(...)` instead, or for the ID "
249 "Codec use `dccl::Codec codec(\"id_codec_name\", MyIDCodec())`.");
252 template <
class Codec>
253 typename std::enable_if<
254 !(std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
255 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value),
257 add(
const std::string& )
259 static_assert(
sizeof(
Codec) == 0,
260 "The global `FieldCodecManager::add<...>(...)` is no longer available. Use "
261 "`dccl::Codec codec; codec.manager().add<...>(...)` instead.`");
264 template <
class Codec, google::protobuf::FieldDescriptor::Type type>
265 static void add(
const std::string& )
267 static_assert(
sizeof(
Codec) == 0,
268 "The global `FieldCodecManager::add<...>(...)` is no longer available. Use "
269 "`dccl::Codec codec; codec.manager().add<...>(...)` instead, or for the ID "
270 "Codec use `dccl::Codec codec(\"id_codec_name\", MyIDCodec())`.");
273 template <
class Codec>
274 typename std::enable_if<
275 std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
276 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value,
278 remove(
const std::string& )
280 static_assert(
sizeof(
Codec) == 0,
281 "The global FieldCodecManager::remove<...>(...) is no longer available. Use "
282 "`dccl::Codec codec; codec.manager().remove<...>(...) instead");
285 template <
class Codec>
286 typename std::enable_if<
287 !(std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
288 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value),
290 remove(
const std::string& )
292 static_assert(
sizeof(
Codec) == 0,
293 "The global FieldCodecManager::remove<...>(...) is no longer available. Use "
294 "`dccl::Codec codec; codec.manager().remove<...>(...) instead");
297 template <
class Codec, google::protobuf::FieldDescriptor::Type type>
298 static void remove(
const std::string& )
300 static_assert(
sizeof(
Codec) == 0,
301 "The global FieldCodecManager::remove<...>(...) is no longer available. Use "
302 "`dccl::Codec codec; codec.manager().remove<...>(...) instead");
308template <
class Codec>
309typename std::enable_if<
310 std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
311 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value,
315 type_helper_.add<
typename Codec::wire_type>();
316 add_single_type<Codec>(
317 __mangle_name(name, std::string(Codec::wire_type::descriptor()->full_name())),
318 google::protobuf::FieldDescriptor::TYPE_MESSAGE,
319 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
322template <
class Codec>
323typename std::enable_if<
324 !(std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
325 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value),
329 add_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name);
332template <
class Codec, google::protobuf::FieldDescriptor::Type type>
335 add_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));
338template <
typename WireType,
typename FieldType,
class Codec>
339void dccl::FieldCodecManagerLocal::add_all_types(
const std::string& name)
341 using google::protobuf::FieldDescriptor;
345 for (
int i = 1, n = FieldDescriptor::MAX_TYPE; i <= n; ++i)
347 auto field_type =
static_cast<FieldDescriptor::Type
>(i);
348 if (FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)
350 add_single_type<Codec>(name, field_type, cpp_wire_type);
355template <
class Codec>
356void dccl::FieldCodecManagerLocal::add_single_type(
357 const std::string& name, google::protobuf::FieldDescriptor::Type field_type,
358 google::protobuf::FieldDescriptor::CppType wire_type)
360 std::shared_ptr<FieldCodecBase> new_field_codec(
new Codec());
361 new_field_codec->set_name(name);
362 new_field_codec->set_field_type(field_type);
363 new_field_codec->set_wire_type(wire_type);
364 new_field_codec->set_manager(
this);
365 using google::protobuf::FieldDescriptor;
366 if (!codecs_[field_type].count(name))
368 codecs_[field_type][name] = new_field_codec;
369 dccl::dlog.
is(dccl::logger::DEBUG1) && dccl::dlog <<
"Adding codec " << *new_field_codec
374 dccl::dlog.
is(dccl::logger::DEBUG1) &&
375 dccl::dlog <<
"Trying to add: " << *new_field_codec
376 <<
", but already have duplicate codec (For `name`/`field type` pair) "
377 << *(codecs_[field_type].find(name)->second) << std::endl;
381template <
class Codec>
382typename std::enable_if<
383 std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
384 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value,
388 type_helper_.remove<
typename Codec::wire_type>();
389 remove_single_type<Codec>(
390 __mangle_name(name, std::string(Codec::wire_type::descriptor()->full_name())),
391 google::protobuf::FieldDescriptor::TYPE_MESSAGE,
392 google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
395template <
class Codec>
396typename std::enable_if<
397 !(std::is_base_of<google::protobuf::Message, typename Codec::wire_type>::value &&
398 !std::is_same<google::protobuf::Message, typename Codec::wire_type>::value),
402 remove_all_types<typename Codec::wire_type, typename Codec::field_type, Codec>(name);
405template <
class Codec, google::protobuf::FieldDescriptor::Type type>
408 remove_single_type<Codec>(name, type, google::protobuf::FieldDescriptor::TypeToCppType(type));
411template <
typename WireType,
typename FieldType,
class Codec>
412void dccl::FieldCodecManagerLocal::remove_all_types(
const std::string& name)
414 using google::protobuf::FieldDescriptor;
418 for (
int i = 1, n = FieldDescriptor::MAX_TYPE; i <= n; ++i)
420 auto field_type =
static_cast<FieldDescriptor::Type
>(i);
421 if (FieldDescriptor::TypeToCppType(field_type) == cpp_field_type)
423 remove_single_type<Codec>(name, field_type, cpp_wire_type);
428template <
class Codec>
429void dccl::FieldCodecManagerLocal::remove_single_type(
430 const std::string& name, google::protobuf::FieldDescriptor::Type field_type,
431 google::protobuf::FieldDescriptor::CppType wire_type)
433 using google::protobuf::FieldDescriptor;
434 if (codecs_[field_type].count(name))
436 dccl::dlog.
is(dccl::logger::DEBUG1) &&
437 dccl::dlog <<
"Removing codec " << *codecs_[field_type][name] << std::endl;
438 codecs_[field_type].erase(name);
442 std::shared_ptr<FieldCodecBase> new_field_codec(
new Codec());
443 new_field_codec->set_name(name);
444 new_field_codec->set_field_type(field_type);
445 new_field_codec->set_wire_type(wire_type);
446 new_field_codec->set_manager(
this);
448 dccl::dlog.
is(dccl::logger::DEBUG1) && dccl::dlog
449 <<
"Trying to remove: " << *new_field_codec
450 <<
", but no such codec exists" << std::endl;
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
A class for managing the various field codecs. Here you can add and remove field codecs....
std::enable_if< std::is_base_of< google::protobuf::Message, typenameCodec::wire_type >::value &&!std::is_same< google::protobuf::Message, typenameCodec::wire_type >::value, void >::type remove(const std::string &name)
Remove a new field codec (used for codecs operating on statically generated Protobuf messages,...
std::enable_if< std::is_base_of< google::protobuf::Message, typenameCodec::wire_type >::value &&!std::is_same< google::protobuf::Message, typenameCodec::wire_type >::value, void >::type add(const std::string &name)
Add a new field codec (used for codecs operating on statically generated Protobuf messages,...
std::shared_ptr< FieldCodecBase > find(const google::protobuf::FieldDescriptor *field, int codec_version, bool has_codec_group, const std::string &codec_group) const
Find the codec for a given field. For embedded messages, prefers (dccl.field).codec (inside field) ov...
std::shared_ptr< FieldCodecBase > find(const google::protobuf::Descriptor *desc, int codec_version=0, std::string name="") const
Find the codec for a given base (or embedded) message.
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Dynamic Compact Control Language namespace.