Skip to content

Commit 398176b

Browse files
committed
IChannel throws exception in case of unupported type.
1 parent 92a3b5a commit 398176b

File tree

7 files changed

+183
-37
lines changed

7 files changed

+183
-37
lines changed

serialization/capnproto/capnproto/include/ecal/msg/capnproto/serializer.h

+31-11
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,22 @@ namespace eCAL
5151
public:
5252
static DatatypeInformation GetDataTypeInformation()
5353
{
54-
DatatypeInformation topic_info;
55-
topic_info.encoding = eCAL::capnproto::EncodingAsString();
56-
topic_info.name = eCAL::capnproto::TypeAsString<T>();
57-
topic_info.descriptor = eCAL::capnproto::SchemaAsString<T>();
58-
return topic_info;
54+
static const DatatypeInformation datatype_info = []() {
55+
DatatypeInformation topic_info;
56+
topic_info.encoding = eCAL::capnproto::EncodingAsString();
57+
topic_info.name = eCAL::capnproto::TypeAsString<T>();
58+
topic_info.descriptor = eCAL::capnproto::SchemaAsString<T>();
59+
return topic_info;
60+
}();
61+
return datatype_info;
62+
}
63+
64+
static bool AcceptsDataWithType(const DatatypeInformation& data_type_info)
65+
{
66+
const auto& own_data_type_info = GetDataTypeInformation();
67+
return
68+
data_type_info.encoding == own_data_type_info.encoding
69+
&& data_type_info.name == own_data_type_info.name ;
5970
}
6071

6172
size_t MessageSize(const capnp::MallocMessageBuilder& message_builder_) const
@@ -104,11 +115,20 @@ namespace eCAL
104115
public:
105116
static DatatypeInformation GetDataTypeInformation()
106117
{
107-
DatatypeInformation topic_info;
108-
topic_info.encoding = eCAL::capnproto::EncodingAsString();
109-
topic_info.name = "*";
110-
topic_info.descriptor = "*";
111-
return topic_info;
118+
static const DatatypeInformation datatype_info = []() {
119+
DatatypeInformation topic_info;
120+
topic_info.encoding = eCAL::capnproto::EncodingAsString();
121+
topic_info.name = "*";
122+
topic_info.descriptor = "*";
123+
return topic_info;
124+
}();
125+
return datatype_info;
126+
}
127+
128+
static bool AcceptsDataWithType(const DatatypeInformation& datatype_info)
129+
{
130+
const auto& own_data_type_info = GetDataTypeInformation();
131+
return datatype_info.encoding == own_data_type_info.encoding;
112132
}
113133

114134
// This function is NOT threadsafe!!!
@@ -142,7 +162,7 @@ namespace eCAL
142162
}
143163
return m_schema_map[datatype_info_];
144164
}
145-
165+
146166
capnp::MallocMessageBuilder m_msg_builder;
147167
std::map<DatatypeInformation, capnp::Schema> m_schema_map;
148168
capnp::SchemaLoader m_loader;

serialization/common/common/include/ecal/msg/exception.h

+72-2
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,88 @@
2020
#pragma once
2121

2222
#include <exception>
23+
#include <sstream>
2324
#include <string>
2425

2526
namespace eCAL
2627
{
27-
/* @cond */
28+
/**
29+
* @brief Exception thrown when an error occurs during deserialization.
30+
*
31+
* This exception is raised when any kind of error occurs during the deserialization process,
32+
* such as when the data is corrupt or does not match the expected format.
33+
*/
2834
class DeserializationException : public std::exception
2935
{
3036
public:
37+
/**
38+
* @brief Constructs a new DeserializationException object.
39+
*
40+
* Initializes the exception with a descriptive error message.
41+
*
42+
* @param message A string containing a detailed description of the error.
43+
*/
3144
DeserializationException(const std::string& message) : message_(message) {}
3245
virtual const char* what() const noexcept { return message_.c_str(); }
3346
private:
3447
std::string message_;
3548
};
36-
/* @endcond */
49+
50+
/**
51+
* @brief Exception thrown when a given datatype is incompatible with a serializer.
52+
*
53+
* This exception is raised when a serializer cannot accept the provided datatype,
54+
* for example when creating an input channel or subscriber. It encapsulates both the
55+
* expected and the actual datatype information to facilitate debugging and error handling.
56+
*
57+
* @tparam DatatypeInformation A type that holds information about a datatype.
58+
* It is expected to have at least the members `encoding` and `name`.
59+
*/
60+
template<typename DatatypeInformation>
61+
class TypeMismatchException : public std::exception
62+
{
63+
public:
64+
/**
65+
* @brief Constructs a new TypeMismatchException object.
66+
*
67+
* Initializes the exception with the expected and actual datatype information.
68+
* An error message is generated detailing the mismatch between the two datatypes.
69+
*
70+
* @param expected_datatype_ The datatype information that was expected.
71+
* @param actual_datatype_ The datatype information that was actually provided.
72+
*/
73+
TypeMismatchException(const DatatypeInformation& expected_datatype_,
74+
const DatatypeInformation& actual_datatype_)
75+
: expected_datatype(expected_datatype_),
76+
actual_datatype(actual_datatype_)
77+
{
78+
std::ostringstream oss;
79+
oss << "Type Mismatch error: Expected and actual datatypes do not match\n"
80+
<< "Expected type:\n"
81+
<< " encoding: " << expected_datatype.encoding << "\n"
82+
<< " name: " << expected_datatype.name << "\n"
83+
<< "Actual type:\n"
84+
<< " encoding: " << actual_datatype.encoding << "\n"
85+
<< " name: " << actual_datatype.name << "\n";
86+
error_message = oss.str();
87+
}
88+
89+
virtual const char* what() const noexcept override {
90+
return error_message.c_str();
91+
}
92+
93+
// Optionally, add accessors for the datatype information.
94+
const DatatypeInformation& getExpectedDatatype() const noexcept {
95+
return expected_datatype;
96+
}
97+
98+
const DatatypeInformation& getActualDatatype() const noexcept {
99+
return actual_datatype;
100+
}
101+
102+
private:
103+
const DatatypeInformation expected_datatype;
104+
const DatatypeInformation actual_datatype;
105+
std::string error_message; // Store the error message persistently.
106+
};
37107
}

serialization/common/common/include/ecal/msg/imeasurement.h

+8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <memory>
2323
#include <set>
24+
#include <sstream>
2425
#include <string>
2526
#include <utility>
2627
#include <stdexcept>
@@ -46,6 +47,13 @@ namespace eCAL
4647
: m_serializer{std::make_shared<Serializer>()}
4748
, binary_channel(std::move(binary_channel_))
4849
{
50+
// We are trying to create a "strong" type, based on only a channel name
51+
// There is a good chance, that the created channel does not match the data
52+
// In this case, we will throw an exception, to make the user aware.
53+
if (!m_serializer->AcceptsDataWithType(GetDataypeInformation()))
54+
{
55+
throw TypeMismatchException<eCAL::experimental::measurement::base::DataTypeInformation>(m_serializer->GetDataTypeInformation(), GetDataypeInformation());
56+
}
4957
}
5058

5159
~IMessageChannel() = default;

serialization/flatbuffers/flatbuffers/include/ecal/msg/flatbuffers/serializer.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,29 @@ namespace eCAL
3333
{
3434
namespace internal
3535
{
36+
/*
37+
* Some restrictions:
38+
* - The generated flatbuffers code does not contain information like descriptors or typenames
39+
* Those have to be generated additionally, thus they are not available for the DatatypeInformation.
40+
*/
3641
template <typename ObjectType, typename DatatypeInformation>
3742
class BaseSerializer
3843
{
3944
public:
4045
static DatatypeInformation GetDataTypeInformation()
4146
{
4247
DatatypeInformation topic_info{};
43-
topic_info.encoding = "flatb";
48+
topic_info.encoding = m_encoding;
4449
// empty type, empty descriptor
4550
return topic_info;
4651
}
52+
53+
static bool AcceptsDataWithType(const DatatypeInformation& datatype_info)
54+
{
55+
return datatype_info.encoding == m_encoding;
56+
}
57+
private:
58+
static constexpr const char* m_encoding = "flatb";
4759
};
4860

4961
/*

serialization/protobuf/protobuf/include/ecal/msg/protobuf/dynamic_serializer.h

+28-12
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,20 @@ namespace eCAL
8787
public:
8888
static DatatypeInformation GetDataTypeInformation()
8989
{
90-
DatatypeInformation topic_info;
91-
topic_info.encoding = "proto";
92-
topic_info.name = "*";
93-
topic_info.descriptor = "*";
94-
return topic_info;
90+
static const DatatypeInformation datatype_info = []() {
91+
DatatypeInformation topic_info;
92+
topic_info.encoding = "proto";
93+
topic_info.name = "*";
94+
topic_info.descriptor = "*";
95+
return topic_info;
96+
}();
97+
return datatype_info;
98+
}
99+
100+
static bool AcceptsDataWithType(const DatatypeInformation& datatype_info_)
101+
{
102+
const auto& own_data_type_info = GetDataTypeInformation();
103+
return datatype_info_.encoding == own_data_type_info.encoding;
95104
}
96105

97106
std::string Deserialize(const void* buffer_, size_t size_, const DatatypeInformation& datatype_info_)
@@ -171,7 +180,6 @@ namespace eCAL
171180
return type_name.substr(type_name.find_last_of('.') + 1, type_name.size());
172181
}
173182

174-
175183
eCAL::protobuf::CProtoDynDecoder m_dynamic_decoder;
176184
std::map<DatatypeInformation, std::shared_ptr<google::protobuf::util::TypeResolver>> m_type_resolver_map;
177185
};
@@ -182,13 +190,21 @@ namespace eCAL
182190
public:
183191
static DatatypeInformation GetDataTypeInformation()
184192
{
185-
DatatypeInformation topic_info;
186-
topic_info.encoding = "proto";
187-
topic_info.name = "*";
188-
topic_info.descriptor = "*";
189-
return topic_info;
193+
static const DatatypeInformation datatype_info = []() {
194+
DatatypeInformation topic_info;
195+
topic_info.encoding = "proto";
196+
topic_info.name = "*";
197+
topic_info.descriptor = "*";
198+
return topic_info;
199+
}();
200+
return datatype_info;
201+
}
202+
203+
static bool AcceptsDataWithType(const DatatypeInformation& datatype_info_)
204+
{
205+
const auto& own_data_type_info = GetDataTypeInformation();
206+
return datatype_info_.encoding == own_data_type_info.encoding;
190207
}
191-
192208

193209
std::shared_ptr<google::protobuf::Message> Deserialize(const void* buffer_, size_t size_, const DatatypeInformation& datatype_info_)
194210
{

serialization/protobuf/protobuf/include/ecal/msg/protobuf/serializer.h

+17-6
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,23 @@ namespace eCAL
4040
public:
4141
static DatatypeInformation GetDataTypeInformation()
4242
{
43-
DatatypeInformation topic_info{};
44-
static T msg{};
45-
topic_info.encoding = "proto";
46-
topic_info.name = msg.GetTypeName();
47-
topic_info.descriptor = protobuf::GetProtoMessageDescription(msg);
48-
return topic_info;
43+
static const DatatypeInformation datatype_info = []() {
44+
DatatypeInformation info{};
45+
T msg{};
46+
info.encoding = "proto";
47+
info.name = msg.GetTypeName();
48+
info.descriptor = protobuf::GetProtoMessageDescription(msg);
49+
return info;
50+
}();
51+
return datatype_info;
52+
}
53+
54+
static bool AcceptsDataWithType(const DatatypeInformation& datatype_info_)
55+
{
56+
const auto& own_datatype_information = GetDataTypeInformation();
57+
return
58+
datatype_info_.encoding == own_datatype_information.encoding
59+
&& datatype_info_.name == own_datatype_information.name;
4960
}
5061

5162
static size_t MessageSize(const T& msg_)

serialization/string/string/include/ecal/msg/string/serializer.h

+14-5
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,20 @@ namespace eCAL
3939
public:
4040
static DatatypeInformation GetDataTypeInformation()
4141
{
42-
DatatypeInformation data_type_info{};
43-
data_type_info.encoding = "utf-8";
44-
data_type_info.name = "string";
45-
// empty descriptor
46-
return data_type_info;
42+
static const DatatypeInformation datatype_info = []() {
43+
DatatypeInformation datatype_info{};
44+
datatype_info.encoding = "utf-8";
45+
datatype_info.name = "string";
46+
// empty descriptor
47+
return datatype_info;
48+
}();
49+
return datatype_info;
50+
}
51+
52+
static bool AcceptsDataWithType(const DatatypeInformation& datatype_info_)
53+
{
54+
auto own_datatype_information = GetDataTypeInformation();
55+
return datatype_info_ == own_datatype_information;
4756
}
4857

4958
static size_t MessageSize(const T& msg_)

0 commit comments

Comments
 (0)