PrimitiveSerializer.cpp
Go to the documentation of this file.
5 #include <swarmio/data/Helper.h>
6 #include <boost/numeric/conversion/cast.hpp>
7 #include <limits>
8 #include <regex>
9 
10 using namespace swarmros;
11 using namespace swarmros::introspection;
12 
13 static inline void ThrowTypeMismatchException(swarmio::data::Variant::ValueCase sourceType, PrimitiveType targetPrimitiveType, const FieldStack& fieldStack)
14 {
15  auto targetType = swarmio::data::Variant::ValueCase::VALUE_NOT_SET;
16  switch (targetPrimitiveType)
17  {
19  targetType = swarmio::data::Variant::ValueCase::kBoolValue;
20  break;
21 
24  targetType = swarmio::data::Variant::ValueCase::kDoubleValue;
25  break;
26 
32  targetType = swarmio::data::Variant::ValueCase::kIntValue;
33  break;
34 
39  case PrimitiveType::TIME:
40  targetType = swarmio::data::Variant::ValueCase::kUintValue;
41  break;
42 
44  targetType = swarmio::data::Variant::ValueCase::kStringValue;
45  break;
46 
47  default:
48  throw Exception("Unknown primitive type");
49  }
50  throw TypeMismatchException("Unexpected target type for PrimitiveSerializer", fieldStack.GetLocation(), targetType, sourceType);
51 }
52 
53 template<typename T, typename O>
54 static inline void SerializeAs(ros::serialization::OStream& stream, O value, const FieldStack& fieldStack)
55 {
56  try
57  {
58  stream.next((T)boost::numeric_cast<T>(value));
59  }
60  catch (const boost::numeric::bad_numeric_cast&)
61  {
62  throw SchemaMismatchException("Integer out-of-range", fieldStack.GetLocation());
63  }
64 }
65 
66 static inline void SerializeAsBool(ros::serialization::OStream& stream, bool value, const FieldStack& fieldStack)
67 {
68  stream.next((uint8_t)(value ? 1 : 0));
69 }
70 
71 static inline void SerializeAsString(ros::serialization::OStream& stream, const std::string& value, const FieldStack& fieldStack)
72 {
73  uint32_t size = value.size();
74  SerializeAs<uint32_t>(stream, size, fieldStack);
75  memcpy(stream.advance(size), value.c_str(), size);
76 }
77 
78 template<typename O>
79 static void SerializeAsTime(ros::serialization::OStream& stream, O value, const FieldStack& fieldStack)
80 {
81  int32_t secs = value / 1000000000;
82  SerializeAs<int32_t>(stream, secs, fieldStack);
83  if (value < 0)
84  {
85  int32_t nsecs = -(-value % 1000000000);
86  SerializeAs<int32_t>(stream, nsecs, fieldStack);
87  }
88  else
89  {
90  int32_t nsecs = value % 1000000000;
91  SerializeAs<int32_t>(stream, nsecs, fieldStack);
92  }
93 
94 }
95 
96 template<typename O>
97 static void SerializeAsDuration(ros::serialization::OStream& stream, O value, const FieldStack& fieldStack)
98 {
99  if (value < 0)
100  {
101  throw SchemaMismatchException("Integer out-of-range", fieldStack.GetLocation());
102  }
103  else
104  {
105  uint32_t secs = value / 1000000000;
106  SerializeAs<uint32_t>(stream, secs, fieldStack);
107  uint32_t nsecs = value % 1000000000;
108  SerializeAs<uint32_t>(stream, nsecs, fieldStack);
109  }
110 }
111 
112 static inline void SerializeAs(ros::serialization::OStream& stream, int64_t value, PrimitiveType type, const FieldStack& fieldStack)
113 {
114  switch (type)
115  {
116  case PrimitiveType::INT8:
117  SerializeAs<int8_t>(stream, value, fieldStack);
118  break;
119 
121  SerializeAs<int16_t>(stream, value, fieldStack);
122  break;
123 
125  SerializeAs<int32_t>(stream, value, fieldStack);
126  break;
127 
129  SerializeAs<int64_t>(stream, value, fieldStack);
130  break;
131 
133  SerializeAs<uint8_t>(stream, value, fieldStack);
134  break;
135 
137  SerializeAs<uint16_t>(stream, value, fieldStack);
138  break;
139 
141  SerializeAs<uint32_t>(stream, value, fieldStack);
142  break;
143 
145  SerializeAs<uint64_t>(stream, value, fieldStack);
146  break;
147 
149  SerializeAsDuration(stream, value, fieldStack);
150  break;
151 
152  case PrimitiveType::TIME:
153  SerializeAsTime(stream, value, fieldStack);
154  break;
155 
156  default:
157  ThrowTypeMismatchException(swarmio::data::Variant::ValueCase::kIntValue, type, fieldStack);
158  break;
159  }
160 }
161 
162 static inline void SerializeAs(ros::serialization::OStream& stream, uint64_t value, PrimitiveType type, const FieldStack& fieldStack)
163 {
164  switch (type)
165  {
167  SerializeAs<uint8_t>(stream, value, fieldStack);
168  break;
169 
171  SerializeAs<uint16_t>(stream, value, fieldStack);
172  break;
173 
175  SerializeAs<uint32_t>(stream, value, fieldStack);
176  break;
177 
179  SerializeAs<uint64_t>(stream, value, fieldStack);
180  break;
181 
182  case PrimitiveType::INT8:
183  SerializeAs<int8_t>(stream, value, fieldStack);
184  break;
185 
187  SerializeAs<int16_t>(stream, value, fieldStack);
188  break;
189 
191  SerializeAs<int32_t>(stream, value, fieldStack);
192  break;
193 
195  SerializeAs<int64_t>(stream, value, fieldStack);
196  break;
197 
199  SerializeAsDuration(stream, value, fieldStack);
200  break;
201 
202  case PrimitiveType::TIME:
203  SerializeAsTime(stream, value, fieldStack);
204  break;
205 
206  default:
207  ThrowTypeMismatchException(swarmio::data::Variant::ValueCase::kUintValue, type, fieldStack);
208  break;
209  }
210 }
211 
212 static inline void SerializeAs(ros::serialization::OStream& stream, bool value, PrimitiveType type, const FieldStack& fieldStack)
213 {
214  switch (type)
215  {
216  case PrimitiveType::BOOL:
217  SerializeAsBool(stream, value, fieldStack);
218  break;
219 
220  default:
221  ThrowTypeMismatchException(swarmio::data::Variant::ValueCase::kBoolValue, type, fieldStack);
222  break;
223  }
224 }
225 
226 static inline void SerializeAs(ros::serialization::OStream& stream, double value, PrimitiveType type, const FieldStack& fieldStack)
227 {
228  switch (type)
229  {
231  SerializeAs<float>(stream, value, fieldStack);
232  break;
233 
235  SerializeAs<double>(stream, value, fieldStack);
236  break;
237 
238  default:
239  ThrowTypeMismatchException(swarmio::data::Variant::ValueCase::kDoubleValue, type, fieldStack);
240  break;
241  }
242 }
243 
244 static inline void SerializeAs(ros::serialization::OStream& stream, const std::string& value, PrimitiveType type, const FieldStack& fieldStack)
245 {
246  switch (type)
247  {
249  SerializeAsString(stream, value, fieldStack);
250  break;
251 
252  default:
253  ThrowTypeMismatchException(swarmio::data::Variant::ValueCase::kDoubleValue, type, fieldStack);
254  break;
255  }
256 }
257 
258 void PrimitiveSerializer::Serialize(ros::serialization::OStream& stream, const swarmio::data::Variant& value, const FieldStack& fieldStack) const
259 {
261  {
262  IndexedFieldStack current(fieldStack);
263  switch (value.value_case())
264  {
265  case swarmio::data::Variant::ValueCase::kBoolArray:
266  for (const auto e : value.bool_array().elements())
267  {
268  SerializeAs(stream, e, _type, current);
269  ++current;
270  }
271  break;
272 
273  case swarmio::data::Variant::ValueCase::kIntArray:
274  for (const auto e : value.int_array().elements())
275  {
276  SerializeAs(stream, e, _type, current);
277  ++current;
278  }
279  break;
280 
281  case swarmio::data::Variant::ValueCase::kUintArray:
282  for (const auto e : value.uint_array().elements())
283  {
284  SerializeAs(stream, e, _type, current);
285  ++current;
286  }
287  break;
288 
289  case swarmio::data::Variant::ValueCase::kDoubleArray:
290  for (const auto e : value.double_array().elements())
291  {
292  SerializeAs(stream, e, _type, current);
293  ++current;
294  }
295  break;
296 
297  case swarmio::data::Variant::ValueCase::kStringArray:
298  for (const auto& e : value.string_array().elements())
299  {
300  SerializeAs(stream, e, _type, current);
301  ++current;
302  }
303  break;
304 
305  default:
306  ThrowTypeMismatchException(value.value_case(), _type, current);
307  break;
308  }
309  }
310  else
311  {
312  switch (value.value_case())
313  {
314  case swarmio::data::Variant::ValueCase::kBoolValue:
315  SerializeAs(stream, value.bool_value(), _type, fieldStack);
316  break;
317 
318  case swarmio::data::Variant::ValueCase::kIntValue:
319  SerializeAs(stream, value.int_value(), _type, fieldStack);
320  break;
321 
322  case swarmio::data::Variant::ValueCase::kUintValue:
323  SerializeAs(stream, value.uint_value(), _type, fieldStack);
324  break;
325 
326  case swarmio::data::Variant::ValueCase::kDoubleValue:
327  SerializeAs(stream, value.double_value(), _type, fieldStack);
328  break;
329 
330  case swarmio::data::Variant::ValueCase::kStringValue:
331  SerializeAs(stream, value.string_value(), _type, fieldStack);
332  break;
333 
334  default:
335  ThrowTypeMismatchException(value.value_case(), _type, fieldStack);
336  break;
337  }
338  }
339 }
340 
341 template<typename T>
343 {
344  T value;
345  stream.next(value);
346  return value;
347 }
348 
349 template<>
351 {
352  uint8_t value;
353  stream.next(value);
354  return value ? true : false;
355 }
356 
357 template<>
358 inline std::string DeserializeAs(ros::serialization::IStream& stream)
359 {
360  uint32_t length = DeserializeAs<uint32_t>(stream);
361  return std::string((const char*)stream.advance(length), length);
362 }
363 
365 {
366  uint32_t secs = DeserializeAs<uint32_t>(stream);
367  uint32_t nsecs = DeserializeAs<uint32_t>(stream);
368  return secs * 1000000000 + nsecs;
369 }
370 
372 {
373  int32_t secs = DeserializeAs<int32_t>(stream);
374  int32_t nsecs = DeserializeAs<int32_t>(stream);
375  return secs * 1000000000 + nsecs;
376 }
377 
378 swarmio::data::Variant PrimitiveSerializer::Deserialize(ros::serialization::IStream& stream, const FieldStack& fieldStack) const
379 {
380  swarmio::data::Variant value;
381  switch (_type)
382  {
383  case PrimitiveType::BOOL:
384  value.set_bool_value(DeserializeAs<bool>(stream));
385  break;
386 
387  case PrimitiveType::INT8:
388  value.set_int_value(DeserializeAs<int8_t>(stream));
389  break;
390 
392  value.set_uint_value(DeserializeAs<uint8_t>(stream));
393  break;
394 
396  value.set_int_value(DeserializeAs<int16_t>(stream));
397  break;
398 
400  value.set_uint_value(DeserializeAs<uint16_t>(stream));
401  break;
402 
404  value.set_int_value(DeserializeAs<int32_t>(stream));
405  break;
406 
408  value.set_int_value(DeserializeAsDuration(stream));
409  break;
410 
412  value.set_uint_value(DeserializeAs<uint32_t>(stream));
413  break;
414 
415  case PrimitiveType::TIME:
416  value.set_uint_value(DeserializeAsTime(stream));
417  break;
418 
420  value.set_int_value(DeserializeAs<int64_t>(stream));
421  break;
422 
424  value.set_uint_value(DeserializeAs<uint64_t>(stream));
425  break;
426 
428  value.set_double_value(DeserializeAs<float>(stream));
429  break;
430 
432  value.set_double_value(DeserializeAs<double>(stream));
433  break;
434 
436  value.set_string_value(DeserializeAs<std::string>(stream));
437  break;
438 
439  default:
440  throw Exception("Unknown primitive type");
441  }
442  return value;
443 }
444 
445 swarmio::data::Variant PrimitiveSerializer::DeserializeArray(ros::serialization::IStream& stream, uint32_t count, const FieldStack& fieldStack) const
446 {
447  swarmio::data::Variant value;
448  if (count > 0)
449  {
450  for (uint32_t i = 0; i < count; ++i)
451  {
452  switch (_type)
453  {
454  case PrimitiveType::BOOL:
455  value.mutable_bool_array()->add_elements(DeserializeAs<bool>(stream));
456  break;
457 
458  case PrimitiveType::INT8:
459  value.mutable_int_array()->add_elements(DeserializeAs<int8_t>(stream));
460  break;
461 
463  value.mutable_uint_array()->add_elements(DeserializeAs<uint8_t>(stream));
464  break;
465 
467  value.mutable_int_array()->add_elements(DeserializeAs<int16_t>(stream));
468  break;
469 
471  value.mutable_uint_array()->add_elements(DeserializeAs<uint16_t>(stream));
472  break;
473 
475  value.mutable_int_array()->add_elements(DeserializeAs<int32_t>(stream));
476  break;
477 
479  value.mutable_int_array()->add_elements(DeserializeAsDuration(stream));
480  break;
481 
483  value.mutable_uint_array()->add_elements(DeserializeAs<uint32_t>(stream));
484  break;
485 
486  case PrimitiveType::TIME:
487  value.mutable_uint_array()->add_elements(DeserializeAsTime(stream));
488  break;
489 
491  value.mutable_int_array()->add_elements(DeserializeAs<int64_t>(stream));
492  break;
493 
495  value.mutable_uint_array()->add_elements(DeserializeAs<uint64_t>(stream));
496  break;
497 
499  value.mutable_double_array()->add_elements(DeserializeAs<float>(stream));
500  break;
501 
503  value.mutable_double_array()->add_elements(DeserializeAs<double>(stream));
504  break;
505 
507  value.mutable_string_array()->add_elements(DeserializeAs<std::string>(stream));
508  break;
509 
510  default:
511  throw Exception("Unknown primitive type");
512  }
513  }
514  }
515  else
516  {
517  switch (_type)
518  {
519  case PrimitiveType::BOOL:
520  value.mutable_bool_array();
521  break;
522 
523  case PrimitiveType::INT8:
524  value.mutable_int_array();
525  break;
526 
528  value.mutable_uint_array();
529  break;
530 
532  value.mutable_int_array();
533  break;
534 
536  value.mutable_uint_array();
537  break;
538 
540  value.mutable_int_array();
541  break;
542 
544  value.mutable_int_array();
545  break;
546 
548  value.mutable_uint_array();
549  break;
550 
551  case PrimitiveType::TIME:
552  value.mutable_uint_array();
553  break;
554 
556  value.mutable_int_array();
557  break;
558 
560  value.mutable_uint_array();
561  break;
562 
564  value.mutable_double_array();
565  break;
566 
568  value.mutable_double_array();
569  break;
570 
572  value.mutable_string_array();
573  break;
574 
575  default:
576  throw Exception("Unknown primitive type");
577  }
578  }
579  return value;
580 }
581 
582 uint32_t PrimitiveSerializer::GetDefaultLength(const FieldStack& fieldStack) const
583 {
584  switch (_type)
585  {
586  case PrimitiveType::BOOL:
587  case PrimitiveType::INT8:
589  return 1;
590 
593  return 2;
594 
599  return 4;
600 
604  case PrimitiveType::TIME:
606  return 8;
607 
608  default:
609  throw Exception("Unknown primitive type");
610  }
611 }
612 
613 uint32_t PrimitiveSerializer::CalculateSerializedLength(const swarmio::data::Variant& value, const FieldStack& fieldStack) const
614 {
615  // Determine length and expected type
616  uint32_t length = 0;
617  swarmio::data::Variant::ValueCase expectedType;
618  switch (_type)
619  {
620  case PrimitiveType::BOOL:
621  expectedType = swarmio::data::Variant::ValueCase::kBoolValue;
622  length = 1;
623  break;
624 
625  case PrimitiveType::INT8:
626  expectedType = swarmio::data::Variant::ValueCase::kIntValue;
627  length = 1;
628  break;
629 
631  expectedType = swarmio::data::Variant::ValueCase::kUintValue;
632  length = 1;
633  break;
634 
636  expectedType = swarmio::data::Variant::ValueCase::kIntValue;
637  length = 2;
638  break;
639 
641  expectedType = swarmio::data::Variant::ValueCase::kUintValue;
642  length = 2;
643  break;
644 
646  expectedType = swarmio::data::Variant::ValueCase::kIntValue;
647  length = 4;
648  break;
649 
651  expectedType = swarmio::data::Variant::ValueCase::kUintValue;
652  length = 4;
653  break;
654 
656  expectedType = swarmio::data::Variant::ValueCase::kDoubleValue;
657  length = 4;
658  break;
659 
662  expectedType = swarmio::data::Variant::ValueCase::kIntValue;
663  length = 8;
664  break;
665 
667  case PrimitiveType::TIME:
668  expectedType = swarmio::data::Variant::ValueCase::kUintValue;
669  length = 8;
670  break;
671 
673  expectedType = swarmio::data::Variant::ValueCase::kDoubleValue;
674  length = 8;
675  break;
676 
678  expectedType = swarmio::data::Variant::ValueCase::kStringValue;
679  length = 4;
680  break;
681 
682  default:
683  throw Exception("Unknown primitive type");
684  }
685 
686  // Check type
687  auto baseType = swarmio::data::Helper::GetBaseType(value);
688  if (baseType == swarmio::data::Variant::ValueCase::kUintValue && expectedType == swarmio::data::Variant::ValueCase::kIntValue)
689  {
690  baseType = expectedType;
691  }
692  else if (baseType == swarmio::data::Variant::ValueCase::kIntValue && expectedType == swarmio::data::Variant::ValueCase::kUintValue)
693  {
694  baseType = expectedType;
695  }
696  if (expectedType != baseType)
697  {
698  throw TypeMismatchException(
699  "Unexpected source type for PrimitiveSerializer",
700  fieldStack.GetLocation(),
701  expectedType,
702  baseType);
703  }
704 
705  // Handle string size, multiply by array count, then return value
706  uint32_t count = swarmio::data::Helper::GetCount(value);
708  {
709  if (count > 1)
710  {
711  // Add length definitions
712  length = length * value.string_array().elements_size();
713 
714  // Add actual characters
715  for (const auto& element : value.string_array().elements())
716  {
717  length += element.size();
718  }
719  }
720  else
721  {
722  // Add actual characters
723  length += value.string_value().size();
724  }
725  }
726  else
727  {
728  // Multiply by array count
729  length *= count;
730  }
731  return length;
732 }
733 
735 {
736  switch (_type)
737  {
738  case PrimitiveType::BOOL:
739  SerializeAs<bool>(stream, false, fieldStack);
740  break;
741 
742  case PrimitiveType::INT8:
743  SerializeAs<int8_t>(stream, 0, fieldStack);
744  break;
745 
747  SerializeAs<int16_t>(stream, 0, fieldStack);
748  break;
749 
751  SerializeAs<int32_t>(stream, 0, fieldStack);
752  break;
753 
755  SerializeAs<int32_t>(stream, 0, fieldStack);
756  SerializeAs<int32_t>(stream, 0, fieldStack);
757  break;
758 
760  SerializeAs<int64_t>(stream, 0, fieldStack);
761  break;
762 
764  SerializeAs<uint8_t>(stream, 0, fieldStack);
765  break;
766 
768  SerializeAs<uint16_t>(stream, 0, fieldStack);
769  break;
770 
772  SerializeAs<uint32_t>(stream, 0, fieldStack);
773  break;
774 
775  case PrimitiveType::TIME:
776  SerializeAs<uint32_t>(stream, 0, fieldStack);
777  SerializeAs<uint32_t>(stream, 0, fieldStack);
778  break;
779 
781  SerializeAs<uint64_t>(stream, 0, fieldStack);
782  break;
783 
785  SerializeAs<float>(stream, 0.0, fieldStack);
786  break;
787 
789  SerializeAs<double>(stream, 0.0, fieldStack);
790  break;
791 
793  SerializeAsString(stream, "", fieldStack);
794  break;
795 
796  default:
797  throw Exception("Unknown primitive type");
798  }
799 }
800 
801 swarmio::data::discovery::Field PrimitiveSerializer::GetFieldDescriptor() const
802 {
803  swarmio::data::discovery::Field field;
804  switch (_type)
805  {
806  case PrimitiveType::BOOL:
807  field.set_type(swarmio::data::discovery::BOOL);
808  break;
809 
810  case PrimitiveType::INT8:
815  field.set_type(swarmio::data::discovery::INT);
816  break;
817 
822  case PrimitiveType::TIME:
823  field.set_type(swarmio::data::discovery::UINT);
824  break;
825 
828  field.set_type(swarmio::data::discovery::DOUBLE);
829  break;
830 
832  field.set_type(swarmio::data::discovery::STRING);
833  break;
834 
835  default:
836  throw Exception("Unknown primitive type");
837  }
838  return field;
839 }
840 
static Variant::ValueCase GetBaseType(const Variant &value)
Get the base type of the variant array, or its type if it is not an array.
Definition: Helper.cpp:53
static void SerializeAsTime(ros::serialization::OStream &stream, O value, const FieldStack &fieldStack)
Exception thrown when the schema does not match the variant.
virtual swarmio::data::Variant Deserialize(ros::serialization::IStream &stream, const FieldStack &fieldStack) const override
Deserialize a stream into a variant.
PrimitiveType
Values correspond to builtin types of the ROS msg specification.
int64_t DeserializeAsDuration(ros::serialization::IStream &stream)
ROS_FORCE_INLINE void next(T &t)
Exception base class for swarmros exceptions.
ROS_FORCE_INLINE uint8_t * advance(uint32_t len)
virtual void Serialize(ros::serialization::OStream &stream, const swarmio::data::Variant &value, const FieldStack &fieldStack) const override
Serialize a variant onto a stream.
static void SerializeAsDuration(ros::serialization::OStream &stream, O value, const FieldStack &fieldStack)
virtual std::string GetLocation() const =0
Construct the current location.
static void SerializeAsBool(ros::serialization::OStream &stream, bool value, const FieldStack &fieldStack)
virtual void EmitDefault(ros::serialization::OStream &stream, const FieldStack &fieldStack) const override
Write the default value to the stream.
static size_t GetCount(const Variant &value)
Get the item count of the variant array, or 1 if it is not an array.
Definition: Helper.cpp:26
uint64_t DeserializeAsTime(ros::serialization::IStream &stream)
static bool IsArray(const Variant &value)
Check whether the variant contains an array type.
Definition: Helper.cpp:10
virtual uint32_t GetDefaultLength(const FieldStack &fieldStack) const override
Get the length of the default value.
static void SerializeAsString(ros::serialization::OStream &stream, const std::string &value, const FieldStack &fieldStack)
static void ThrowTypeMismatchException(swarmio::data::Variant::ValueCase sourceType, PrimitiveType targetPrimitiveType, const FieldStack &fieldStack)
virtual swarmio::data::discovery::Field GetFieldDescriptor() const override
Build a field descriptor for the underlying type.
Exception thrown when the expected type of the Variant does not match the actual type.
virtual uint32_t CalculateSerializedLength(const swarmio::data::Variant &value, const FieldStack &fieldStack) const override
Calculate the length of a serialized message in bytes.
static void SerializeAs(ros::serialization::OStream &stream, O value, const FieldStack &fieldStack)
virtual swarmio::data::Variant DeserializeArray(ros::serialization::IStream &stream, uint32_t count, const FieldStack &fieldStack) const override
Deserialize a stream into a variant array.
ROS_FORCE_INLINE void next(const T &t)
static T DeserializeAs(ros::serialization::IStream &stream)


swarmros
Author(s):
autogenerated on Fri Apr 3 2020 03:42:48