DCCL v5
Loading...
Searching...
No Matches
protobuf_cpp_type_helpers.h
1// Copyright 2014-2023:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7//
8//
9// This file is part of the Dynamic Compact Control Language Library
10// ("DCCL").
11//
12// DCCL is free software: you can redistribute it and/or modify
13// it under the terms of the GNU Lesser General Public License as published by
14// the Free Software Foundation, either version 2.1 of the License, or
15// (at your option) any later version.
16//
17// DCCL is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Lesser General Public License for more details.
21//
22// You should have received a copy of the GNU Lesser General Public License
23// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
24#ifndef DCCLPROTOBUFCPPTYPEHELPERS20110323H
25#define DCCLPROTOBUFCPPTYPEHELPERS20110323H
26
27#include "../any.h"
28
29#include <google/protobuf/descriptor.h>
30#include <google/protobuf/descriptor.pb.h>
31#include <google/protobuf/message.h>
32
33namespace dccl
34{
35namespace internal
36{
39{
40 public:
41 virtual ~FromProtoTypeBase() = default;
43 virtual std::string as_str() { return "TYPE_UNKNOWN"; }
44};
45
46template <google::protobuf::FieldDescriptor::Type t> class FromProtoType : public FromProtoTypeBase
47{
48 public:
49 std::string as_str() override
50 {
51 return google::protobuf::FieldDescriptorProto::Type_Name(
52 static_cast<google::protobuf::FieldDescriptorProto::Type>(t));
53 }
54};
55
58{
59 public:
60 virtual ~FromProtoCppTypeBase() = default;
61
63 virtual std::string as_str() { return "CPPTYPE_UNKNOWN"; }
64
70 dccl::any get_value(const google::protobuf::FieldDescriptor* field,
71 const google::protobuf::Message& msg)
72 {
73 // For fields without presence tracking (proto3 singular scalar fields without the
74 // `optional` keyword), HasField() is not valid. Such fields always have a value
75 // (defaulting to 0/false/empty if not explicitly set), so we always return it.
76 if (!field->has_presence())
77 return _get_value(field, msg);
78 const google::protobuf::Reflection* refl = msg.GetReflection();
79 if (!refl->HasField(msg, field))
80 return dccl::any();
81 else
82 return _get_value(field, msg);
83 }
84
86 dccl::any get_value(const google::protobuf::Message& msg) { return _get_value(nullptr, msg); }
87
94 dccl::any get_repeated_value(const google::protobuf::FieldDescriptor* field,
95 const google::protobuf::Message& msg, int index)
96 {
97 return _get_repeated_value(field, msg, index);
98 }
99
105 void set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
106 dccl::any value)
107 {
108 if (is_empty(value))
109 return;
110 else
111 _set_value(field, msg, value);
112 }
113
115 void set_value(google::protobuf::Message* msg, dccl::any value)
116 {
117 if (is_empty(value))
118 return;
119 else
120 _set_value(nullptr, msg, value);
121 }
122
127 void add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
128 dccl::any value)
129 {
130 if (is_empty(value))
131 return;
132 else
133 _add_value(field, msg, value);
134 }
135
136 virtual void _set_value(const google::protobuf::FieldDescriptor* /*field*/,
137 google::protobuf::Message* /*msg*/, dccl::any /*value*/)
138 {
139 return;
140 }
141
142 virtual void _add_value(const google::protobuf::FieldDescriptor* /*field*/,
143 google::protobuf::Message* /*msg*/, dccl::any /*value*/)
144 {
145 return;
146 }
147
148 virtual dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* /*field*/,
149 const google::protobuf::Message& /*msg*/, int /*index*/)
150 {
151 return dccl::any();
152 }
153
154 virtual dccl::any _get_value(const google::protobuf::FieldDescriptor* /*field*/,
155 const google::protobuf::Message& /*msg*/)
156 {
157 return dccl::any();
158 }
159};
160
161template <google::protobuf::FieldDescriptor::CppType> class FromProtoCppType
162{
163};
164template <>
165class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE>
166 : public FromProtoCppTypeBase
167{
168 public:
169 using type = double;
170 std::string as_str() override { return "CPPTYPE_DOUBLE"; }
171
172 private:
173 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
174 const google::protobuf::Message& msg) override
175 {
176 return msg.GetReflection()->GetDouble(msg, field);
177 }
178 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
179 const google::protobuf::Message& msg, int index) override
180 {
181 return msg.GetReflection()->GetRepeatedDouble(msg, field, index);
182 }
183 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
184 dccl::any value) override
185 {
186 msg->GetReflection()->SetDouble(msg, field, dccl::any_cast<type>(value));
187 }
188 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
189 dccl::any value) override
190 {
191 msg->GetReflection()->AddDouble(msg, field, dccl::any_cast<type>(value));
192 }
193};
194
195template <>
196class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_FLOAT>
197 : public FromProtoCppTypeBase
198{
199 public:
200 using type = float;
201 std::string as_str() override { return "CPPTYPE_FLOAT"; }
202
203 private:
204 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
205 const google::protobuf::Message& msg) override
206 {
207 return msg.GetReflection()->GetFloat(msg, field);
208 }
209 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
210 const google::protobuf::Message& msg, int index) override
211 {
212 return msg.GetReflection()->GetRepeatedFloat(msg, field, index);
213 }
214 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
215 dccl::any value) override
216 {
217 msg->GetReflection()->SetFloat(msg, field, dccl::any_cast<type>(value));
218 }
219 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
220 dccl::any value) override
221 {
222 msg->GetReflection()->AddFloat(msg, field, dccl::any_cast<type>(value));
223 }
224};
225template <>
226class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_INT32>
227 : public FromProtoCppTypeBase
228{
229 public:
230 using type = google::protobuf::int32;
231 std::string as_str() override { return "CPPTYPE_INT32"; }
232
233 private:
234 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
235 const google::protobuf::Message& msg) override
236 {
237 return msg.GetReflection()->GetInt32(msg, field);
238 }
239 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
240 const google::protobuf::Message& msg, int index) override
241 {
242 return msg.GetReflection()->GetRepeatedInt32(msg, field, index);
243 }
244 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
245 dccl::any value) override
246 {
247 msg->GetReflection()->SetInt32(msg, field, dccl::any_cast<type>(value));
248 }
249 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
250 dccl::any value) override
251 {
252 msg->GetReflection()->AddInt32(msg, field, dccl::any_cast<type>(value));
253 }
254};
255template <>
256class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_INT64>
257 : public FromProtoCppTypeBase
258{
259 public:
260 using type = google::protobuf::int64;
261 std::string as_str() override { return "CPPTYPE_INT64"; }
262
263 private:
264 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
265 const google::protobuf::Message& msg) override
266 {
267 return msg.GetReflection()->GetInt64(msg, field);
268 }
269 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
270 const google::protobuf::Message& msg, int index) override
271 {
272 return msg.GetReflection()->GetRepeatedInt64(msg, field, index);
273 }
274 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
275 dccl::any value) override
276 {
277 msg->GetReflection()->SetInt64(msg, field, dccl::any_cast<type>(value));
278 }
279 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
280 dccl::any value) override
281 {
282 msg->GetReflection()->AddInt64(msg, field, dccl::any_cast<type>(value));
283 }
284};
285template <>
286class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_UINT32>
287 : public FromProtoCppTypeBase
288{
289 public:
290 using type = google::protobuf::uint32;
291 std::string as_str() override { return "CPPTYPE_UINT32"; }
292
293 private:
294 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
295 const google::protobuf::Message& msg) override
296 {
297 return msg.GetReflection()->GetUInt32(msg, field);
298 }
299 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
300 const google::protobuf::Message& msg, int index) override
301 {
302 return msg.GetReflection()->GetRepeatedUInt32(msg, field, index);
303 }
304 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
305 dccl::any value) override
306 {
307 msg->GetReflection()->SetUInt32(msg, field, dccl::any_cast<type>(value));
308 }
309 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
310 dccl::any value) override
311 {
312 msg->GetReflection()->AddUInt32(msg, field, dccl::any_cast<type>(value));
313 }
314};
315template <>
316class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_UINT64>
317 : public FromProtoCppTypeBase
318{
319 public:
320 using type = google::protobuf::uint64;
321
322 std::string as_str() override { return "CPPTYPE_UINT64"; }
323
324 private:
325 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
326 const google::protobuf::Message& msg) override
327 {
328 return msg.GetReflection()->GetUInt64(msg, field);
329 }
330 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
331 const google::protobuf::Message& msg, int index) override
332 {
333 return msg.GetReflection()->GetRepeatedUInt64(msg, field, index);
334 }
335 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
336 dccl::any value) override
337 {
338 msg->GetReflection()->SetUInt64(msg, field, dccl::any_cast<type>(value));
339 }
340 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
341 dccl::any value) override
342 {
343 msg->GetReflection()->AddUInt64(msg, field, dccl::any_cast<type>(value));
344 }
345};
346template <>
347class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_BOOL>
348 : public FromProtoCppTypeBase
349{
350 public:
351 using type = bool;
352 std::string as_str() override { return "CPPTYPE_BOOL"; }
353
354 private:
355 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
356 const google::protobuf::Message& msg) override
357 {
358 return msg.GetReflection()->GetBool(msg, field);
359 }
360 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
361 const google::protobuf::Message& msg, int index) override
362 {
363 return msg.GetReflection()->GetRepeatedBool(msg, field, index);
364 }
365 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
366 dccl::any value) override
367 {
368 msg->GetReflection()->SetBool(msg, field, dccl::any_cast<type>(value));
369 }
370 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
371 dccl::any value) override
372 {
373 msg->GetReflection()->AddBool(msg, field, dccl::any_cast<type>(value));
374 }
375};
376template <>
377class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_STRING>
378 : public FromProtoCppTypeBase
379{
380 public:
381 using type = std::string;
382 std::string as_str() override { return "CPPTYPE_STRING"; }
383
384 private:
385 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
386 const google::protobuf::Message& msg) override
387 {
388 return msg.GetReflection()->GetString(msg, field);
389 }
390 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
391 const google::protobuf::Message& msg, int index) override
392 {
393 return msg.GetReflection()->GetRepeatedString(msg, field, index);
394 }
395 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
396 dccl::any value) override
397 {
398 msg->GetReflection()->SetString(msg, field, dccl::any_cast<type>(value));
399 }
400 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
401 dccl::any value) override
402 {
403 msg->GetReflection()->AddString(msg, field, dccl::any_cast<type>(value));
404 }
405};
406
407template <>
408class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_ENUM>
409 : public FromProtoCppTypeBase
410{
411 public:
412 using const_type = const google::protobuf::EnumValueDescriptor*;
413 using mutable_type = google::protobuf::EnumValueDescriptor*;
414
415 std::string as_str() override { return "CPPTYPE_ENUM"; }
416
417 private:
418 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
419 const google::protobuf::Message& msg) override
420 {
421 return msg.GetReflection()->GetEnum(msg, field);
422 }
423 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
424 const google::protobuf::Message& msg, int index) override
425 {
426 return msg.GetReflection()->GetRepeatedEnum(msg, field, index);
427 }
428 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
429 dccl::any value) override
430 {
431 msg->GetReflection()->SetEnum(msg, field, dccl::any_cast<const_type>(value));
432 }
433 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
434 dccl::any value) override
435 {
436 msg->GetReflection()->AddEnum(msg, field, dccl::any_cast<const_type>(value));
437 }
438};
439
441template <>
442class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE>
443 : public FromProtoCppTypeBase
444{
445 public:
446 using const_type = const google::protobuf::Message*;
447 using mutable_type = google::protobuf::Message*;
448 std::string as_str() override { return "CPPTYPE_MESSAGE"; }
449
450 protected:
451 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
452 const google::protobuf::Message& msg) override
453 {
454 if (field)
455 return &(msg.GetReflection()->GetMessage(msg, field));
456 else
457 return &msg;
458 }
459
460 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
461 const google::protobuf::Message& msg, int index) override
462 {
463 return &(msg.GetReflection()->GetRepeatedMessage(msg, field, index));
464 }
465
466 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
467 dccl::any value) override
468 {
469 try
470 {
471 auto p = dccl::any_cast<const_type>(value);
472
473 if (field)
474 msg->GetReflection()->MutableMessage(msg, field)->MergeFrom(*p);
475 else
476 msg->MergeFrom(*p);
477 }
478 catch (dccl::bad_any_cast& e)
479 {
480 auto p = dccl::any_cast<mutable_type>(value);
481 if (field)
482 msg->GetReflection()->MutableMessage(msg, field)->MergeFrom(*p);
483 else
484 msg->MergeFrom(*p);
485 }
486 }
487 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
488 dccl::any value) override
489 {
490 try
491 {
492 auto p = dccl::any_cast<const_type>(value);
493 msg->GetReflection()->AddMessage(msg, field)->MergeFrom(*p);
494 }
495 catch (dccl::bad_any_cast& e)
496 {
497 auto p = dccl::any_cast<mutable_type>(value);
498 msg->GetReflection()->AddMessage(msg, field)->MergeFrom(*p);
499 }
500 }
501};
502
504template <typename CustomMessage>
506 : public FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE>
507{
508 public:
509 using type = CustomMessage;
510
511 private:
513
514 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
515 const google::protobuf::Message& msg) override
516 {
517 auto p = dccl::any_cast<Parent::const_type>(Parent::_get_value(field, msg));
518 type r;
519 r.CopyFrom(*p);
520 return r;
521 // return dynamic_cast<const_type>(*p);
522 }
523 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
524 const google::protobuf::Message& msg, int index) override
525 {
526 auto p = dccl::any_cast<Parent::const_type>(Parent::_get_repeated_value(field, msg, index));
527 type r;
528 r.CopyFrom(*p);
529 return r;
530 // return dynamic_cast<const_type>(*p);
531 }
532 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
533 dccl::any value) override
534 {
535 type v = dccl::any_cast<type>(value);
536 Parent::const_type p = &v;
537 Parent::_set_value(field, msg, p);
538 }
539 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
540 dccl::any value) override
541 {
542 type v = dccl::any_cast<type>(value);
543 Parent::const_type p = &v;
544 Parent::_add_value(field, msg, p);
545 }
546};
547
548template <typename T> class ToProtoCppType
549{
550};
551template <> class ToProtoCppType<double>
552{
553 public:
554 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
555 {
556 return google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE;
557 }
558};
559template <> class ToProtoCppType<float>
560{
561 public:
562 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
563 {
564 return google::protobuf::FieldDescriptor::CPPTYPE_FLOAT;
565 }
566};
567template <> class ToProtoCppType<google::protobuf::int32>
568{
569 public:
570 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
571 {
572 return google::protobuf::FieldDescriptor::CPPTYPE_INT32;
573 }
574};
575template <> class ToProtoCppType<google::protobuf::uint32>
576{
577 public:
578 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
579 {
580 return google::protobuf::FieldDescriptor::CPPTYPE_UINT32;
581 }
582};
583template <> class ToProtoCppType<google::protobuf::int64>
584{
585 public:
586 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
587 {
588 return google::protobuf::FieldDescriptor::CPPTYPE_INT64;
589 }
590};
591template <> class ToProtoCppType<google::protobuf::uint64>
592{
593 public:
594 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
595 {
596 return google::protobuf::FieldDescriptor::CPPTYPE_UINT64;
597 }
598};
599template <> class ToProtoCppType<std::string>
600{
601 public:
602 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
603 {
604 return google::protobuf::FieldDescriptor::CPPTYPE_STRING;
605 }
606};
607template <> class ToProtoCppType<const google::protobuf::EnumValueDescriptor*>
608{
609 public:
610 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
611 {
612 return google::protobuf::FieldDescriptor::CPPTYPE_ENUM;
613 }
614};
615
616template <> class ToProtoCppType<bool>
617{
618 public:
619 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
620 {
621 return google::protobuf::FieldDescriptor::CPPTYPE_BOOL;
622 }
623};
624
625template <> class ToProtoCppType<google::protobuf::Message>
626{
627 public:
628 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
629 {
630 return google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE;
631 }
632};
633} // namespace internal
634} // namespace dccl
635
636#endif
Provides various representations of a google::protobuf::FieldDescriptor::CppType enumeration,...
dccl::any get_value(const google::protobuf::Message &msg)
Get the value of the entire base message (only works for CPPTYPE_MESSAGE)
dccl::any get_value(const google::protobuf::FieldDescriptor *field, const google::protobuf::Message &msg)
Get a given field's value from the provided message.
virtual std::string as_str()
string representation
void set_value(const google::protobuf::FieldDescriptor *field, google::protobuf::Message *msg, dccl::any value)
Set a given field's value in the provided message.
void set_value(google::protobuf::Message *msg, dccl::any value)
Set the value of the entire base message (only works for CPPTYPE_MESSAGE)
dccl::any get_repeated_value(const google::protobuf::FieldDescriptor *field, const google::protobuf::Message &msg, int index)
Get the value of a repeated field at a given index.
void add_value(const google::protobuf::FieldDescriptor *field, google::protobuf::Message *msg, dccl::any value)
Add a new entry for a repeated field to the back.
Implements FromProtoCppTypeBase for CPPTYPE_MESSAGE using the dynamic google::protobuf::Message as th...
Implements FromProtoCppTypeBase for CPPTYPE_MESSAGE using a specific statically generated Protobuf cl...
Provides various representations of a google::protobuf::FieldDescriptor::Type enumeration....
virtual std::string as_str()
string representation of the google::protobuf::FieldDescriptor::Type.
std::string as_str() override
string representation of the google::protobuf::FieldDescriptor::Type.
Dynamic Compact Control Language namespace.
Definition any.h:28