DCCL v4
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 const google::protobuf::Reflection* refl = msg.GetReflection();
74 if (!refl->HasField(msg, field))
75 return dccl::any();
76 else
77 return _get_value(field, msg);
78 }
79
81 dccl::any get_value(const google::protobuf::Message& msg) { return _get_value(nullptr, msg); }
82
89 dccl::any get_repeated_value(const google::protobuf::FieldDescriptor* field,
90 const google::protobuf::Message& msg, int index)
91 {
92 return _get_repeated_value(field, msg, index);
93 }
94
100 void set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
101 dccl::any value)
102 {
103 if (is_empty(value))
104 return;
105 else
106 _set_value(field, msg, value);
107 }
108
110 void set_value(google::protobuf::Message* msg, dccl::any value)
111 {
112 if (is_empty(value))
113 return;
114 else
115 _set_value(nullptr, msg, value);
116 }
117
122 void add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
123 dccl::any value)
124 {
125 if (is_empty(value))
126 return;
127 else
128 _add_value(field, msg, value);
129 }
130
131 virtual void _set_value(const google::protobuf::FieldDescriptor* /*field*/,
132 google::protobuf::Message* /*msg*/, dccl::any /*value*/)
133 {
134 return;
135 }
136
137 virtual void _add_value(const google::protobuf::FieldDescriptor* /*field*/,
138 google::protobuf::Message* /*msg*/, dccl::any /*value*/)
139 {
140 return;
141 }
142
143 virtual dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* /*field*/,
144 const google::protobuf::Message& /*msg*/, int /*index*/)
145 {
146 return dccl::any();
147 }
148
149 virtual dccl::any _get_value(const google::protobuf::FieldDescriptor* /*field*/,
150 const google::protobuf::Message& /*msg*/)
151 {
152 return dccl::any();
153 }
154};
155
156template <google::protobuf::FieldDescriptor::CppType> class FromProtoCppType
157{
158};
159template <>
160class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE>
161 : public FromProtoCppTypeBase
162{
163 public:
164 using type = double;
165 std::string as_str() override { return "CPPTYPE_DOUBLE"; }
166
167 private:
168 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
169 const google::protobuf::Message& msg) override
170 {
171 return msg.GetReflection()->GetDouble(msg, field);
172 }
173 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
174 const google::protobuf::Message& msg, int index) override
175 {
176 return msg.GetReflection()->GetRepeatedDouble(msg, field, index);
177 }
178 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
179 dccl::any value) override
180 {
181 msg->GetReflection()->SetDouble(msg, field, dccl::any_cast<type>(value));
182 }
183 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
184 dccl::any value) override
185 {
186 msg->GetReflection()->AddDouble(msg, field, dccl::any_cast<type>(value));
187 }
188};
189
190template <>
191class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_FLOAT>
192 : public FromProtoCppTypeBase
193{
194 public:
195 using type = float;
196 std::string as_str() override { return "CPPTYPE_FLOAT"; }
197
198 private:
199 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
200 const google::protobuf::Message& msg) override
201 {
202 return msg.GetReflection()->GetFloat(msg, field);
203 }
204 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
205 const google::protobuf::Message& msg, int index) override
206 {
207 return msg.GetReflection()->GetRepeatedFloat(msg, field, index);
208 }
209 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
210 dccl::any value) override
211 {
212 msg->GetReflection()->SetFloat(msg, field, dccl::any_cast<type>(value));
213 }
214 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
215 dccl::any value) override
216 {
217 msg->GetReflection()->AddFloat(msg, field, dccl::any_cast<type>(value));
218 }
219};
220template <>
221class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_INT32>
222 : public FromProtoCppTypeBase
223{
224 public:
225 using type = google::protobuf::int32;
226 std::string as_str() override { return "CPPTYPE_INT32"; }
227
228 private:
229 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
230 const google::protobuf::Message& msg) override
231 {
232 return msg.GetReflection()->GetInt32(msg, field);
233 }
234 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
235 const google::protobuf::Message& msg, int index) override
236 {
237 return msg.GetReflection()->GetRepeatedInt32(msg, field, index);
238 }
239 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
240 dccl::any value) override
241 {
242 msg->GetReflection()->SetInt32(msg, field, dccl::any_cast<type>(value));
243 }
244 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
245 dccl::any value) override
246 {
247 msg->GetReflection()->AddInt32(msg, field, dccl::any_cast<type>(value));
248 }
249};
250template <>
251class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_INT64>
252 : public FromProtoCppTypeBase
253{
254 public:
255 using type = google::protobuf::int64;
256 std::string as_str() override { return "CPPTYPE_INT64"; }
257
258 private:
259 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
260 const google::protobuf::Message& msg) override
261 {
262 return msg.GetReflection()->GetInt64(msg, field);
263 }
264 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
265 const google::protobuf::Message& msg, int index) override
266 {
267 return msg.GetReflection()->GetRepeatedInt64(msg, field, index);
268 }
269 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
270 dccl::any value) override
271 {
272 msg->GetReflection()->SetInt64(msg, field, dccl::any_cast<type>(value));
273 }
274 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
275 dccl::any value) override
276 {
277 msg->GetReflection()->AddInt64(msg, field, dccl::any_cast<type>(value));
278 }
279};
280template <>
281class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_UINT32>
282 : public FromProtoCppTypeBase
283{
284 public:
285 using type = google::protobuf::uint32;
286 std::string as_str() override { return "CPPTYPE_UINT32"; }
287
288 private:
289 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
290 const google::protobuf::Message& msg) override
291 {
292 return msg.GetReflection()->GetUInt32(msg, field);
293 }
294 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
295 const google::protobuf::Message& msg, int index) override
296 {
297 return msg.GetReflection()->GetRepeatedUInt32(msg, field, index);
298 }
299 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
300 dccl::any value) override
301 {
302 msg->GetReflection()->SetUInt32(msg, field, dccl::any_cast<type>(value));
303 }
304 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
305 dccl::any value) override
306 {
307 msg->GetReflection()->AddUInt32(msg, field, dccl::any_cast<type>(value));
308 }
309};
310template <>
311class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_UINT64>
312 : public FromProtoCppTypeBase
313{
314 public:
315 using type = google::protobuf::uint64;
316
317 std::string as_str() override { return "CPPTYPE_UINT64"; }
318
319 private:
320 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
321 const google::protobuf::Message& msg) override
322 {
323 return msg.GetReflection()->GetUInt64(msg, field);
324 }
325 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
326 const google::protobuf::Message& msg, int index) override
327 {
328 return msg.GetReflection()->GetRepeatedUInt64(msg, field, index);
329 }
330 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
331 dccl::any value) override
332 {
333 msg->GetReflection()->SetUInt64(msg, field, dccl::any_cast<type>(value));
334 }
335 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
336 dccl::any value) override
337 {
338 msg->GetReflection()->AddUInt64(msg, field, dccl::any_cast<type>(value));
339 }
340};
341template <>
342class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_BOOL>
343 : public FromProtoCppTypeBase
344{
345 public:
346 using type = bool;
347 std::string as_str() override { return "CPPTYPE_BOOL"; }
348
349 private:
350 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
351 const google::protobuf::Message& msg) override
352 {
353 return msg.GetReflection()->GetBool(msg, field);
354 }
355 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
356 const google::protobuf::Message& msg, int index) override
357 {
358 return msg.GetReflection()->GetRepeatedBool(msg, field, index);
359 }
360 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
361 dccl::any value) override
362 {
363 msg->GetReflection()->SetBool(msg, field, dccl::any_cast<type>(value));
364 }
365 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
366 dccl::any value) override
367 {
368 msg->GetReflection()->AddBool(msg, field, dccl::any_cast<type>(value));
369 }
370};
371template <>
372class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_STRING>
373 : public FromProtoCppTypeBase
374{
375 public:
376 using type = std::string;
377 std::string as_str() override { return "CPPTYPE_STRING"; }
378
379 private:
380 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
381 const google::protobuf::Message& msg) override
382 {
383 return msg.GetReflection()->GetString(msg, field);
384 }
385 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
386 const google::protobuf::Message& msg, int index) override
387 {
388 return msg.GetReflection()->GetRepeatedString(msg, field, index);
389 }
390 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
391 dccl::any value) override
392 {
393 msg->GetReflection()->SetString(msg, field, dccl::any_cast<type>(value));
394 }
395 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
396 dccl::any value) override
397 {
398 msg->GetReflection()->AddString(msg, field, dccl::any_cast<type>(value));
399 }
400};
401
402template <>
403class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_ENUM>
404 : public FromProtoCppTypeBase
405{
406 public:
407 using const_type = const google::protobuf::EnumValueDescriptor*;
408 using mutable_type = google::protobuf::EnumValueDescriptor*;
409
410 std::string as_str() override { return "CPPTYPE_ENUM"; }
411
412 private:
413 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
414 const google::protobuf::Message& msg) override
415 {
416 return msg.GetReflection()->GetEnum(msg, field);
417 }
418 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
419 const google::protobuf::Message& msg, int index) override
420 {
421 return msg.GetReflection()->GetRepeatedEnum(msg, field, index);
422 }
423 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
424 dccl::any value) override
425 {
426 msg->GetReflection()->SetEnum(msg, field, dccl::any_cast<const_type>(value));
427 }
428 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
429 dccl::any value) override
430 {
431 msg->GetReflection()->AddEnum(msg, field, dccl::any_cast<const_type>(value));
432 }
433};
434
436template <>
437class FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE>
438 : public FromProtoCppTypeBase
439{
440 public:
441 using const_type = const google::protobuf::Message*;
442 using mutable_type = google::protobuf::Message*;
443 std::string as_str() override { return "CPPTYPE_MESSAGE"; }
444
445 protected:
446 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
447 const google::protobuf::Message& msg) override
448 {
449 if (field)
450 return &(msg.GetReflection()->GetMessage(msg, field));
451 else
452 return &msg;
453 }
454
455 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
456 const google::protobuf::Message& msg, int index) override
457 {
458 return &(msg.GetReflection()->GetRepeatedMessage(msg, field, index));
459 }
460
461 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
462 dccl::any value) override
463 {
464 try
465 {
466 auto p = dccl::any_cast<const_type>(value);
467
468 if (field)
469 msg->GetReflection()->MutableMessage(msg, field)->MergeFrom(*p);
470 else
471 msg->MergeFrom(*p);
472 }
473 catch (dccl::bad_any_cast& e)
474 {
475 auto p = dccl::any_cast<mutable_type>(value);
476 if (field)
477 msg->GetReflection()->MutableMessage(msg, field)->MergeFrom(*p);
478 else
479 msg->MergeFrom(*p);
480 }
481 }
482 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
483 dccl::any value) override
484 {
485 try
486 {
487 auto p = dccl::any_cast<const_type>(value);
488 msg->GetReflection()->AddMessage(msg, field)->MergeFrom(*p);
489 }
490 catch (dccl::bad_any_cast& e)
491 {
492 auto p = dccl::any_cast<mutable_type>(value);
493 msg->GetReflection()->AddMessage(msg, field)->MergeFrom(*p);
494 }
495 }
496};
497
499template <typename CustomMessage>
501 : public FromProtoCppType<google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE>
502{
503 public:
504 using type = CustomMessage;
505
506 private:
508
509 dccl::any _get_value(const google::protobuf::FieldDescriptor* field,
510 const google::protobuf::Message& msg) override
511 {
512 auto p = dccl::any_cast<Parent::const_type>(Parent::_get_value(field, msg));
513 type r;
514 r.CopyFrom(*p);
515 return r;
516 // return dynamic_cast<const_type>(*p);
517 }
518 dccl::any _get_repeated_value(const google::protobuf::FieldDescriptor* field,
519 const google::protobuf::Message& msg, int index) override
520 {
521 auto p = dccl::any_cast<Parent::const_type>(Parent::_get_repeated_value(field, msg, index));
522 type r;
523 r.CopyFrom(*p);
524 return r;
525 // return dynamic_cast<const_type>(*p);
526 }
527 void _set_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
528 dccl::any value) override
529 {
530 type v = dccl::any_cast<type>(value);
531 Parent::const_type p = &v;
532 Parent::_set_value(field, msg, p);
533 }
534 void _add_value(const google::protobuf::FieldDescriptor* field, google::protobuf::Message* msg,
535 dccl::any value) override
536 {
537 type v = dccl::any_cast<type>(value);
538 Parent::const_type p = &v;
539 Parent::_add_value(field, msg, p);
540 }
541};
542
543template <typename T> class ToProtoCppType
544{
545};
546template <> class ToProtoCppType<double>
547{
548 public:
549 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
550 {
551 return google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE;
552 }
553};
554template <> class ToProtoCppType<float>
555{
556 public:
557 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
558 {
559 return google::protobuf::FieldDescriptor::CPPTYPE_FLOAT;
560 }
561};
562template <> class ToProtoCppType<google::protobuf::int32>
563{
564 public:
565 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
566 {
567 return google::protobuf::FieldDescriptor::CPPTYPE_INT32;
568 }
569};
570template <> class ToProtoCppType<google::protobuf::uint32>
571{
572 public:
573 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
574 {
575 return google::protobuf::FieldDescriptor::CPPTYPE_UINT32;
576 }
577};
578template <> class ToProtoCppType<google::protobuf::int64>
579{
580 public:
581 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
582 {
583 return google::protobuf::FieldDescriptor::CPPTYPE_INT64;
584 }
585};
586template <> class ToProtoCppType<google::protobuf::uint64>
587{
588 public:
589 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
590 {
591 return google::protobuf::FieldDescriptor::CPPTYPE_UINT64;
592 }
593};
594template <> class ToProtoCppType<std::string>
595{
596 public:
597 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
598 {
599 return google::protobuf::FieldDescriptor::CPPTYPE_STRING;
600 }
601};
602template <> class ToProtoCppType<const google::protobuf::EnumValueDescriptor*>
603{
604 public:
605 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
606 {
607 return google::protobuf::FieldDescriptor::CPPTYPE_ENUM;
608 }
609};
610
611template <> class ToProtoCppType<bool>
612{
613 public:
614 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
615 {
616 return google::protobuf::FieldDescriptor::CPPTYPE_BOOL;
617 }
618};
619
620template <> class ToProtoCppType<google::protobuf::Message>
621{
622 public:
623 static constexpr google::protobuf::FieldDescriptor::CppType as_enum()
624 {
625 return google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE;
626 }
627};
628} // namespace internal
629} // namespace dccl
630
631#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:47