MVSim
Lightweight simulator for 2.5D vehicles and robots
common.h
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2026 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
10 #pragma once
11 
12 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
13 
14 #include <mrpt/io/CMemoryStream.h>
15 #include <mrpt/serialization/CArchive.h>
16 
17 #include <variant>
18 
19 #include "zmq_fwrds.h"
20 
21 namespace google::protobuf
22 {
23 class MessageLite;
24 }
25 
26 namespace mvsim
27 {
38 void sendMessage(const google::protobuf::MessageLite& m, zmq::socket_t& socket);
39 
41 zmq::message_t receiveMessage(zmq::socket_t& s);
42 
49 void parseMessage(const zmq::message_t& msg, google::protobuf::MessageLite& out);
50 
51 class UnexpectedMessageException : public std::runtime_error
52 {
53  public:
54  UnexpectedMessageException(const char* reason) : std::runtime_error(reason) {}
55 };
56 namespace internal
57 {
58 std::tuple<std::string, std::string> parseMessageToParts(const zmq::message_t& msg);
59 
60 template <typename variant_t, size_t IDX = 0>
61 variant_t recursiveParse(const std::string& typeName, const std::string& serializedData)
62 {
63  if constexpr (IDX < std::variant_size_v<variant_t>)
64  {
65  using this_t = std::variant_alternative_t<IDX, variant_t>;
66  this_t v;
67  const std::string expectedName = v.GetTypeName();
68  if (expectedName == typeName)
69  {
70  bool ok = v.ParseFromString(serializedData);
71  if (!ok)
72  {
73  THROW_EXCEPTION_FMT(
74  "Format error: protobuf could not decode binary message of type '%s'",
75  typeName.c_str());
76  }
77  return {v};
78  }
79 
80  return recursiveParse<variant_t, IDX + 1>(typeName, serializedData);
81  }
82  throw UnexpectedMessageException(
83  mrpt::format("Type '%s' not found in expected list of variant arguments.", typeName.c_str())
84  .c_str());
85 }
86 } // namespace internal
87 
88 std::string get_zmq_endpoint(const zmq::socket_t& s);
89 
95 template <typename variant_t>
96 variant_t parseMessageVariant(const zmq::message_t& msg)
97 {
98  const auto [typeName, serializedData] = internal::parseMessageToParts(msg);
99  return internal::recursiveParse<variant_t>(typeName, serializedData);
100 }
101 
103 template <class... Ts>
104 struct overloaded : Ts...
105 {
106  using Ts::operator()...;
107 };
108 
110 template <class... Ts>
111 overloaded(Ts...) -> overloaded<Ts...>;
112 
115 } // namespace mvsim
116 #endif
Definition: common.h:52
overloaded(Ts...) -> overloaded< Ts... >
zmq::message_t receiveMessage(zmq::socket_t &s)
void parseMessage(const zmq::message_t &msg, google::protobuf::MessageLite &out)
void sendMessage(const google::protobuf::MessageLite &m, zmq::socket_t &socket)
variant_t parseMessageVariant(const zmq::message_t &msg)
Definition: common.h:96
Definition: common.h:105