RMW desert 1.0
Loading...
Searching...
No Matches
MessageSerialization.h
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (C) 2024 Davide Costa *
3 * *
4 * This file is part of RMW desert. *
5 * *
6 * RMW desert is free software: you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation, either version 3 of the License, or any *
9 * later version. *
10 * *
11 * RMW desert is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with RMW desert. If not, see <http://www.gnu.org/licenses/>. *
18 ****************************************************************************/
19
34#ifndef MESSAGE_SERIALIZATION_H_
35#define MESSAGE_SERIALIZATION_H_
36
37#include "CBorStream.h"
38#include "CStringHelper.h"
39#include "macros.h"
40
43#include <vector>
44#include <string>
45
48#define INTROSPECTION_C_MEMBER rosidl_typesupport_introspection_c__MessageMember
49#define INTROSPECTION_CPP_MEMBER rosidl_typesupport_introspection_cpp::MessageMember
50
51#define INTROSPECTION_C_MEMBERS rosidl_typesupport_introspection_c__MessageMembers
52#define INTROSPECTION_CPP_MEMBERS rosidl_typesupport_introspection_cpp::MessageMembers
53
54#define INTROSPECTION_C_SERVICE_MEMBERS rosidl_typesupport_introspection_c__ServiceMembers
55#define INTROSPECTION_CPP_SERVICE_MEMBERS rosidl_typesupport_introspection_cpp::ServiceMembers
56
68{
69
81 template<typename T>
82 void serialize_field(const INTROSPECTION_CPP_MEMBER * member, void * field, cbor::TxStream & stream)
83 {
84 if (!member->is_array_)
85 {
86 stream << * static_cast<T *>(field);
87 }
88 else if (member->array_size_ && !member->is_upper_bound_)
89 {
90 stream.serialize_sequence(static_cast<T *>(field), member->array_size_);
91 }
92 else
93 {
94 std::vector<T> & data = *reinterpret_cast<std::vector<T> *>(field);
95 stream << data;
96 }
97 }
98
110 template<typename T>
111 void serialize_field(const INTROSPECTION_C_MEMBER * member, void * field, cbor::TxStream & stream)
112 {
113 // String specific implementation
114 if constexpr(std::is_same_v<T, std::string>)
115 {
116 if (!member->is_array_)
117 {
119 }
120 else if (member->array_size_ && !member->is_upper_bound_)
121 {
122 stream << CStringHelper::convert_to_std_vector_string(field, member->array_size_);
123 }
124 else
125 {
126 printf("WARNING: non-fixed size sequences are currently sperimental\n");
128 }
129 }
130 // U16string specific implementation
131 else if constexpr(std::is_same_v<T, std::u16string>)
132 {
133 if (!member->is_array_)
134 {
136 }
137 else if (member->array_size_ && !member->is_upper_bound_)
138 {
139 stream << CStringHelper::convert_to_std_vector_u16string(field, member->array_size_);
140 }
141 else
142 {
143 printf("WARNING: non-fixed size sequences are currently sperimental\n");
145 }
146 }
147 // Generic implementation
148 else
149 {
150 if (!member->is_array_)
151 {
152 stream << * static_cast<T *>(field);
153 }
154 else if (member->array_size_ && !member->is_upper_bound_)
155 {
156 stream.serialize_sequence(static_cast<T *>(field), member->array_size_);
157 }
158 else
159 {
160 printf("WARNING: non-fixed size sequences are currently sperimental\n");
161 auto & data = *reinterpret_cast<typename GenericCSequence<T>::type *>(field);
162
163 // Serialize length
164 stream << (uint32_t)data.size;
165
166 stream.serialize_sequence(reinterpret_cast<T *>(data.data), data.size);
167 }
168 }
169 }
170
183 template<typename MembersType>
184 void serialize(const void * msg, const MembersType * casted_members, cbor::TxStream & stream)
185 {
186 for (uint32_t i = 0; i < casted_members->member_count_; ++i) {
187 const auto member = casted_members->members_ + i;
188 void * field = const_cast<char *>(static_cast<const char *>(msg)) + member->offset_;
189 switch (member->type_id_) {
190 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE:
191 {
192 auto sub_members = static_cast<const MembersType *>(member->members_->data);
193 if (!member->is_array_) {
194 serialize(field, sub_members, stream);
195 }
196 else if (member->array_size_ && !member->is_upper_bound_)
197 {
198 for (size_t index = 0; index < member->array_size_; ++index) {
199 serialize(member->get_function(field, index), sub_members, stream);
200 }
201 }
202 else
203 {
204 size_t array_size = member->size_function(field);
205
206 if (member->is_upper_bound_ && array_size > member->array_size_)
207 {
208 throw std::runtime_error("Sequence overcomes the maximum length");
209 }
210
211 // Serialize length
212 stream << (uint32_t)array_size;
213
214 for (size_t index = 0; index < array_size; ++index) {
215 serialize(member->get_function(field, index), sub_members, stream);
216 }
217 }
218 }
219 break;
220 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_BOOLEAN:
221 if (!member->is_array_)
222 {
223 // Don't cast to bool here because if the bool is uninitialized the random value can't be deserialized
224 stream << (*static_cast<uint8_t *>(field) ? true : false);
225 }
226 else
227 {
229 }
230 break;
231 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_OCTET:
232 //throw std::runtime_error("OCTET type unsupported");
233 break;
234 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT8:
236 break;
237 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_CHAR:
239 break;
240 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT8:
242 break;
243 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_FLOAT:
245 break;
246 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_DOUBLE:
248 break;
249 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT16:
251 break;
252 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT16:
254 break;
255 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT32:
257 break;
258 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT32:
260 break;
261 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT64:
263 break;
264 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT64:
266 break;
267 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING:
269 break;
270 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_WSTRING:
272 break;
273 default:
274 throw std::runtime_error("unknown type");
275 }
276 }
277 }
278
290 template<typename T>
291 void deserialize_field(const INTROSPECTION_CPP_MEMBER * member, void * field, cbor::RxStream & stream)
292 {
293 if (!member->is_array_) {
294 stream >> *static_cast<T *>(field);
295 }
296 else if (member->array_size_ && !member->is_upper_bound_)
297 {
298 stream.deserialize_sequence(static_cast<T *>(field), member->array_size_);
299 }
300 else
301 {
302 auto & vector = *reinterpret_cast<std::vector<T> *>(field);
303 new(&vector) std::vector<T>;
304 stream >> vector;
305 }
306 }
307
319 template<typename T>
320 void deserialize_field(const INTROSPECTION_C_MEMBER * member, void * field, cbor::RxStream & stream)
321 {
322 // String specific implementation
323 if constexpr(std::is_same_v<T, std::string>)
324 {
325 if (!member->is_array_)
326 {
327 std::string str;
328 stream >> str;
330 }
331 else if (member->array_size_ && !member->is_upper_bound_)
332 {
333 std::vector<std::string> cpp_string_vector;
335
337 }
338 else
339 {
340 printf("WARNING: non-fixed size sequences are currently sperimental\n");
341 std::vector<std::string> cpp_string_vector;
343
345 }
346 }
347 // U16string specific implementation
348 else if constexpr(std::is_same_v<T, std::u16string>)
349 {
350 if (!member->is_array_)
351 {
352 std::u16string str;
353 stream >> str;
355 }
356 else if (member->array_size_ && !member->is_upper_bound_)
357 {
358 std::vector<std::u16string> cpp_string_vector;
360
362 }
363 else
364 {
365 printf("WARNING: non-fixed size sequences are currently sperimental\n");
366 std::vector<std::u16string> cpp_string_vector;
368
370 }
371 }
372 // Generic implementation
373 else
374 {
375 if (!member->is_array_)
376 {
377 stream >> * static_cast<T *>(field);
378 }
379 else if (member->array_size_ && !member->is_upper_bound_)
380 {
381 stream.deserialize_sequence(static_cast<T *>(field), member->array_size_);
382 }
383 else
384 {
385 printf("WARNING: non-fixed size sequences are currently sperimental\n");
386 auto & data = *reinterpret_cast<typename GenericCSequence<T>::type *>(field);
387 uint32_t size = 0;
388 stream >> size;
389 size_t dsize = static_cast<size_t>(size);
390
392 {
393 throw std::runtime_error("unable to initialize GenericCSequence");
394 }
395
396 stream.deserialize_sequence(reinterpret_cast<T *>(data.data), dsize);
397 }
398 }
399 }
400
414 template<typename MembersType>
416 {
417 for (uint32_t i = 0; i < casted_members->member_count_; ++i) {
418 const auto member = casted_members->members_ + i;
419 void * field = static_cast<char *>(msg) + member->offset_;
420 switch (member->type_id_) {
421 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE:
422 {
423 auto sub_members = static_cast<const MembersType *>(member->members_->data);
424 if (!member->is_array_) {
426 }
427 else if (member->array_size_ && !member->is_upper_bound_)
428 {
429 for (size_t index = 0; index < member->array_size_; ++index) {
430 deserialize(member->get_function(field, index), sub_members, stream);
431 }
432 }
433 else
434 {
435 // Deserialize length
438
439 auto vector = reinterpret_cast<std::vector<unsigned char> *>(field);
440 new(vector) std::vector<unsigned char>;
441 member->resize_function(field, array_size);
442
443 for (size_t index = 0; index < array_size; ++index) {
444 deserialize(member->get_function(field, index), sub_members, stream);
445 }
446 }
447 }
448 break;
449 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_BOOLEAN:
451 break;
452 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_OCTET:
453 //throw std::runtime_error("OCTET type unsupported");
454 break;
455 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT8:
457 break;
458 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_CHAR:
460 break;
461 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT8:
463 break;
464 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_FLOAT:
466 break;
467 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_DOUBLE:
469 break;
470 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT16:
472 break;
473 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT16:
475 break;
476 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT32:
478 break;
479 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT32:
481 break;
482 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_INT64:
484 break;
485 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_UINT64:
487 break;
488 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING:
490 break;
491 case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_WSTRING:
493 break;
494 default:
495 throw std::runtime_error("unknown type");
496 }
497 }
498 }
499
500}
501
502
503#endif
Classes used to convert data types into a CBOR encoded stream.
Namespace containing C sequence handling functions.
Definition CBorStream.h:244
Definition CBorStream.h:87
TxStream & serialize_sequence(const T *items, size_t size)
Serialize a sequence of uniform elements.
Definition CBorStream.h:218
Header containing C sequence macros.
void assign_vector_string(std::vector< std::string > cpp_string_vector, void *str_array, size_t size)
Assing to a rosidl_runtime_c__String the value contained in a vector of std::string.
Definition CStringHelper.cpp:69
void assign_vector_u16string_to_sequence(std::vector< std::u16string > cpp_string_vector, void *str_seq)
Assing to a rosidl_runtime_c__U16String__Sequence the value contained in a vector of std::u16string.
Definition CStringHelper.cpp:117
std::vector< std::string > convert_to_std_vector_string(void *str_array, size_t size)
Convert a rosidl_runtime_c__String into a vector of std::string.
Definition CStringHelper.cpp:9
std::u16string convert_to_std_u16string(void *str)
Convert a rosidl_runtime_c__U16String into std::u16string.
Definition CStringHelper.cpp:33
std::vector< std::u16string > convert_to_std_vector_u16string(void *str_array, size_t size)
Convert a rosidl_runtime_c__U16String into a vector of std::u16string.
Definition CStringHelper.cpp:39
void assign_vector_string_to_sequence(std::vector< std::string > cpp_string_vector, void *str_seq)
Assing to a rosidl_runtime_c__String__Sequence the value contained in a vector of std::string.
Definition CStringHelper.cpp:81
std::vector< std::u16string > convert_sequence_to_std_vector_u16string(void *str_seq)
Convert a rosidl_runtime_c__U16String__Sequence into a vector of std::u16string.
Definition CStringHelper.cpp:51
void assign_string(std::string str, void *field)
Assing to a rosidl_runtime_c__String the value contained in a std::string.
Definition CStringHelper.cpp:63
void assign_u16string(std::u16string str, void *field)
Assing to a rosidl_runtime_c__U16String the value contained in a std::u16string.
Definition CStringHelper.cpp:99
void assign_vector_u16string(std::vector< std::u16string > cpp_string_vector, void *str_array, size_t size)
Assing to a rosidl_runtime_c__U16String the value contained in a vector of std::u16string.
Definition CStringHelper.cpp:105
std::vector< std::string > convert_sequence_to_std_vector_string(void *str_seq)
Convert a rosidl_runtime_c__String__Sequence into a vector of std::string.
Definition CStringHelper.cpp:21
std::string convert_to_std_string(void *str)
Convert a rosidl_runtime_c__String into std::string.
Definition CStringHelper.cpp:3
Namespace containing serialization functions.
void serialize_field(const INTROSPECTION_CPP_MEMBER *member, void *field, cbor::TxStream &stream)
Serialize a C++ field.
Definition MessageSerialization.h:82
void deserialize(void *msg, const MembersType *casted_members, cbor::RxStream &stream)
Deserialize a ROS message, request or response.
Definition MessageSerialization.h:415
void serialize(const void *msg, const MembersType *casted_members, cbor::TxStream &stream)
Serialize a ROS message, request or response.
Definition MessageSerialization.h:184
void deserialize_field(const INTROSPECTION_CPP_MEMBER *member, void *field, cbor::RxStream &stream)
Deserialize a C++ field.
Definition MessageSerialization.h:291
Definition macros.h:58