DCCL v5
Loading...
Searching...
No Matches
default_field_codec.h
1// Copyright 2023:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Dynamic Compact Control Language Library
9// ("DCCL").
10//
11// DCCL is free software: you can redistribute it and/or modify
12// it under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// DCCL is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
23#include "codec.h"
24
25#ifndef CODEC_VERSION
26#error CODEC_VERSION must be set
27#endif
28
29#ifndef CODEC_VERSION_NAMESPACE
30#error CODEC_VERSION_NAMESPACE must be set
31#endif
32
33#ifndef DCCL_DEFAULT_FIELD_CODEC_HEADER_H
34#define DCCL_DEFAULT_FIELD_CODEC_HEADER_H
35
36namespace dccl
37{
38
39namespace internal
40{
41
42//
43// Helper functions to reduce copy/paste in set_default_codecs()
44//
45template <int version> struct DefaultFieldCodecLoader
46{
47 static_assert(sizeof(DefaultFieldCodecLoader) == 0,
48 "Must use specialization of DefaultFieldCodecLoader");
49};
50
51template <int version> struct TimeCodecLoader
52{
53 static_assert(sizeof(TimeCodecLoader) == 0, "Must use specialization of TimeCodecLoader");
54};
55
56template <int version> struct StaticCodecLoader
57{
58 static_assert(sizeof(StaticCodecLoader) == 0, "Must use specialization of StaticCodecLoader");
59};
60
61template <int version> struct PresenceCodecLoader
62{
63 static_assert(sizeof(PresenceCodecLoader) == 0,
64 "Must use specialization of PresenceCodecLoader");
65};
66
67template <int version> struct VarBytesCodecLoader
68{
69 static_assert(sizeof(VarBytesCodecLoader) == 0,
70 "Must use specialization of VarBytesCodecLoader");
71};
72
73template <int version> struct HashCodecLoader
74{
75 static_assert(sizeof(HashCodecLoader) == 0, "Must use specialization of HashCodecLoader");
76};
77
78template <int version> struct CRCCodecLoader
79{
80 static_assert(sizeof(CRCCodecLoader) == 0, "Must use specialization of CRCCodecLoader");
81};
82
83} // namespace internal
84} // namespace dccl
85#endif
86
87namespace dccl
88{
89namespace internal
90{
91// replace recursion with C++ 17 fold expression when we switch to C++ 17 or newer
92template <> struct DefaultFieldCodecLoader<CODEC_VERSION>
93{
94 // entry
95 static void add(FieldCodecManagerLocal& manager)
96 {
97 using namespace CODEC_VERSION_NAMESPACE;
98 using google::protobuf::FieldDescriptor;
99
100 std::string name = ::dccl::Codec::default_codec_name(CODEC_VERSION);
101 manager.add<DefaultBoolCodec>(name);
102 manager.add<DefaultStringCodec, FieldDescriptor::TYPE_STRING>(name);
103 manager.add<DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(name);
104 manager.add<DefaultEnumCodec>(name);
105 manager.add<DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(name);
106
107 add<true, double, float, int32, int64, uint32, uint64>(manager);
108 }
109
110 // recurse
111 template <bool enable, typename T, typename... Types>
112 static void add(FieldCodecManagerLocal& manager)
113 {
114 using namespace CODEC_VERSION_NAMESPACE;
115 std::string name = ::dccl::Codec::default_codec_name(CODEC_VERSION);
116 manager.add<DefaultNumericFieldCodec<T>>(name);
117 // recurse
118 add<enable, Types...>(manager);
119 }
120
121 // last
122 template <bool enable> static void add(FieldCodecManagerLocal& manager) {}
123};
124
125template <int version> struct TimeCodecLoader;
126template <> struct TimeCodecLoader<CODEC_VERSION>
127{
128 static void add(FieldCodecManagerLocal& manager,
129 const std::string& name = "dccl.time" + std::to_string(CODEC_VERSION))
130 {
131 add<true, double, int64, uint64>(manager, name);
132 }
133
134 template <bool enable, typename T, typename... Types>
135 static void add(FieldCodecManagerLocal& manager, const std::string& name)
136 {
137 using namespace CODEC_VERSION_NAMESPACE;
138 manager.add<TimeCodec<T>>(name);
139 add<enable, Types...>(manager, name);
140 }
141 template <bool enable> static void add(FieldCodecManagerLocal& manager, const std::string& name)
142 {
143 }
144};
145
146template <> struct StaticCodecLoader<CODEC_VERSION>
147{
148 static void add(FieldCodecManagerLocal& manager,
149 const std::string& name = "dccl.static" + std::to_string(CODEC_VERSION))
150 {
151 add<true, std::string, double, float, int32, int64, uint32, uint64>(manager, name);
152 }
153
154 template <bool enable, typename T, typename... Types>
155 static void add(FieldCodecManagerLocal& manager, const std::string& name)
156 {
157 using namespace CODEC_VERSION_NAMESPACE;
158 manager.add<StaticCodec<T>>(name);
159 add<enable, Types...>(manager, name);
160 }
161
162 template <bool enable> static void add(FieldCodecManagerLocal& manager, const std::string& name)
163 {
164 }
165};
166
167#if CODEC_VERSION >= 3
168template <> struct PresenceCodecLoader<CODEC_VERSION>
169{
170 static void add(FieldCodecManagerLocal& manager)
171 {
172 using namespace CODEC_VERSION_NAMESPACE;
173 using google::protobuf::FieldDescriptor;
174
175 manager.add<PresenceBitCodec<DefaultBoolCodec>>(name_);
176 manager.add<PresenceBitCodec<DefaultStringCodec>, FieldDescriptor::TYPE_STRING>(name_);
177 manager.add<PresenceBitCodec<DefaultBytesCodec>, FieldDescriptor::TYPE_BYTES>(name_);
178 manager.add<PresenceBitCodec<DefaultEnumCodec>>(name_);
179
180 // use normal default meessage codec
181 manager.add<DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(name_);
182 add<true, double, float, int32, int64, uint32, uint64>(manager);
183 }
184
185 template <bool enable, typename T, typename... Types>
186 static void add(FieldCodecManagerLocal& manager)
187 {
188 using namespace CODEC_VERSION_NAMESPACE;
189 std::string name = ::dccl::Codec::default_codec_name(CODEC_VERSION);
190 manager.add<PresenceBitCodec<DefaultNumericFieldCodec<T>>>(name_);
191 add<enable, Types...>(manager);
192 }
193
194 template <bool enable> static void add(FieldCodecManagerLocal& manager) {}
195
196 private:
197 static const std::string name_;
198};
199
200const std::string PresenceCodecLoader<CODEC_VERSION>::name_{"dccl.presence" +
201 std::to_string(CODEC_VERSION)};
202
203template <> struct VarBytesCodecLoader<CODEC_VERSION>
204{
205 static void add(FieldCodecManagerLocal& manager)
206 {
207 using namespace CODEC_VERSION_NAMESPACE;
208 manager.add<VarBytesCodec>("dccl.var_bytes" + std::to_string(CODEC_VERSION));
209 }
210};
211
212#endif
213
214#if CODEC_VERSION >= 4
215template <> struct HashCodecLoader<CODEC_VERSION>
216{
217 static void add(FieldCodecManagerLocal& manager, std::set<int> versions = {CODEC_VERSION})
218 {
219 using namespace CODEC_VERSION_NAMESPACE;
220 // backport versions
221 for (int v : versions) manager.add<HashCodec>("dccl.hash" + std::to_string(v));
222 }
223};
224
225template <> struct CRCCodecLoader<CODEC_VERSION>
226{
227 static void add(FieldCodecManagerLocal& manager, std::set<int> versions = {CODEC_VERSION})
228 {
229 using namespace CODEC_VERSION_NAMESPACE;
230 // Register version-suffixed names for backwards compatibility
231 for (int v : versions)
232 {
233 manager.add<CRC16Codec>("dccl.crc16" + std::to_string(v));
234 manager.add<CRC32Codec>("dccl.crc32" + std::to_string(v));
235 }
236 // Register plain names so users can write codec: "dccl.crc16" or "dccl.crc32".
237 // The FieldCodecManager auto-appends the codec version only when the name does NOT
238 // end in a digit, so "dccl.crc16" and "dccl.crc32" (which end in digits) must be
239 // registered explicitly without a version suffix.
240 manager.add<CRC16Codec>("dccl.crc16");
241 manager.add<CRC32Codec>("dccl.crc32");
242 }
243};
244
245#endif
246
247} // namespace internal
248} // namespace dccl
249
250#undef CODEC_VERSION
251#undef CODEC_VERSION_NAMESPACE
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 add(const std::string &name)
Add a new field codec (used for codecs operating on statically generated Protobuf messages,...
Dynamic Compact Control Language namespace.
Definition any.h:28