Skip to content

Commit 3eb2c6e

Browse files
committed
Catch jsoncons exceptions to return rfl::Error
1 parent 23fc6c2 commit 3eb2c6e

4 files changed

Lines changed: 41 additions & 79 deletions

File tree

include/rfl/cbor/read.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,31 @@ using InputVarType = typename Reader::InputVarType;
2020
/// Parses an object from CBOR using reflection.
2121
template <class T, class... Ps>
2222
Result<internal::wrap_in_rfl_array_t<T>> read(const std::vector<char>& _bytes) {
23-
auto val = jsoncons::cbor::decode_cbor<jsoncons::json>(_bytes);
24-
auto r = Reader();
25-
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
23+
// TODO: Use a non-throwing decode_cbor(), pending https://github.com/danielaparker/jsoncons/issues/615
24+
try {
25+
auto val = jsoncons::cbor::decode_cbor<jsoncons::json>(_bytes);
26+
auto r = Reader();
27+
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
28+
} catch(const jsoncons::ser_error& e) {
29+
std::string error("Could not parse CBOR: ");
30+
error.append(e.what());
31+
return rfl::error(error);
32+
}
2633
}
2734

2835
/// Parses an object from a stream.
2936
template <class T, class... Ps>
3037
Result<internal::wrap_in_rfl_array_t<T>> read(std::istream& _stream) {
31-
auto val = jsoncons::cbor::decode_cbor<jsoncons::json>(_stream);
32-
auto r = Reader();
33-
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
38+
// TODO: Use a non-throwing decode_cbor(), pending https://github.com/danielaparker/jsoncons/issues/615
39+
try {
40+
auto val = jsoncons::cbor::decode_cbor<jsoncons::json>(_stream);
41+
auto r = Reader();
42+
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
43+
} catch(const jsoncons::ser_error& e) {
44+
std::string error("Could not parse CBOR: ");
45+
error.append(e.what());
46+
return rfl::error(error);
47+
}
3448
}
3549

3650
} // namespace rfl::cbor

include/rfl/ubjson/read.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,31 @@ using InputVarType = typename Reader::InputVarType;
2020
/// Parses an object from UBJSON using reflection.
2121
template <class T, class... Ps>
2222
Result<internal::wrap_in_rfl_array_t<T>> read(const std::vector<char>& _bytes) {
23-
auto val = jsoncons::ubjson::decode_ubjson<jsoncons::json>(_bytes);
24-
auto r = Reader();
25-
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
23+
// TODO: Use a non-throwing decode_ubjson(), pending https://github.com/danielaparker/jsoncons/issues/615
24+
try {
25+
auto val = jsoncons::ubjson::decode_ubjson<jsoncons::json>(_bytes);
26+
auto r = Reader();
27+
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
28+
} catch(const jsoncons::ser_error& e) {
29+
std::string error("Could not parse UBJSON: ");
30+
error.append(e.what());
31+
return rfl::error(error);
32+
}
2633
}
2734

2835
/// Parses an object from a stream.
2936
template <class T, class... Ps>
3037
Result<internal::wrap_in_rfl_array_t<T>> read(std::istream& _stream) {
31-
auto val = jsoncons::ubjson::decode_ubjson<jsoncons::json>(_stream);
32-
auto r = Reader();
33-
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
38+
// TODO: Use a non-throwing decode_ubjson(), pending https://github.com/danielaparker/jsoncons/issues/615
39+
try {
40+
auto val = jsoncons::ubjson::decode_ubjson<jsoncons::json>(_stream);
41+
auto r = Reader();
42+
return Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
43+
} catch(const jsoncons::ser_error& e) {
44+
std::string error("Could not parse UBJSON: ");
45+
error.append(e.what());
46+
return rfl::error(error);
47+
}
3448
}
3549

3650
} // namespace rfl::ubjson

tests/cbor/test_error_messages.cpp

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -34,40 +34,7 @@ TEST(cbor, test_field_error_messages) {
3434
EXPECT_EQ(result.error().what(), expected);
3535
}
3636

37-
TEST(cbor, test_decode_error_causes_exception) {
38-
const std::string good_string =
39-
R"({"firstName":"Homer","lastName":"Simpson","birthday":"1987-04-19"})";
40-
const auto good_generic = rfl::json::read<rfl::Generic>(good_string);
41-
auto faulty_cbor = rfl::cbor::write(good_generic);
42-
faulty_cbor[1] = '\xff'; // Corrupt structure of CBOR encoding
43-
44-
rfl::Result<Person> result = rfl::error("result didn't get set");
45-
EXPECT_THROW({
46-
try
47-
{
48-
result = rfl::cbor::read<Person>(faulty_cbor);
49-
}
50-
catch( const jsoncons::ser_error& e )
51-
{
52-
// and this tests that it has the correct message
53-
const std::string expected = R"(An unknown type was found in the stream at position 1)";
54-
EXPECT_EQ( e.what(), expected );
55-
throw;
56-
}
57-
}, jsoncons::ser_error );
58-
59-
const std::string expected = R"(result didn't get set)";
60-
EXPECT_EQ(result.error().what(), expected);
61-
62-
EXPECT_TRUE(!result.has_value() && true);
63-
}
64-
6537
TEST(cbor, test_decode_error_without_exception) {
66-
GTEST_SKIP() << "Expected failing test represents future ideal behavior";
67-
// This test is expected to fail because the error handling in the CBOR library
68-
// doesn't return an error result, but rather throw exceptions. The test is
69-
// written to demonstrate the desired behavior, but the actual implementation
70-
// may not support this yet.
7138
const std::string good_string =
7239
R"({"firstName":"Homer","lastName":"Simpson","birthday":"1987-04-19"})";
7340
const auto good_generic = rfl::json::read<rfl::Generic>(good_string);

tests/ubjson/test_error_messages.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,40 +34,7 @@ TEST(ubjson, test_field_error_messages) {
3434
EXPECT_EQ(result.error().what(), expected);
3535
}
3636

37-
TEST(ubjson, test_decode_error_causes_exception) {
38-
const std::string good_string =
39-
R"({"firstName":"Homer","lastName":"Simpson","birthday":"1987-04-19"})";
40-
const auto good_generic = rfl::json::read<rfl::Generic>(good_string);
41-
auto faulty_ubjson = rfl::ubjson::write(good_generic);
42-
faulty_ubjson[0] = '\xff'; // Corrupt structure of ubjson encoding
43-
44-
rfl::Result<Person> result = rfl::error("result didn't get set");
45-
EXPECT_THROW({
46-
try
47-
{
48-
result = rfl::ubjson::read<Person>(faulty_ubjson);
49-
}
50-
catch( const jsoncons::ser_error& e )
51-
{
52-
// and this tests that it has the correct message
53-
const std::string expected = R"(Unknown type at position 1)";
54-
EXPECT_EQ( e.what(), expected );
55-
throw;
56-
}
57-
}, jsoncons::ser_error );
58-
59-
const std::string expected = R"(result didn't get set)";
60-
EXPECT_EQ(result.error().what(), expected);
61-
62-
EXPECT_TRUE(!result.has_value() && true);
63-
}
64-
6537
TEST(ubjson, test_decode_error_without_exception) {
66-
GTEST_SKIP() << "Expected failing test represents future ideal behavior";
67-
// This test is expected to fail because the error handling in the UBJSON library
68-
// doesn't return an error result, but rather throw exceptions. The test is
69-
// written to demonstrate the desired behavior, but the actual implementation
70-
// may not support this yet.
7138
const std::string good_string =
7239
R"({"firstName":"Homer","lastName":"Simpson","birthday":"1987-04-19"})";
7340
const auto good_generic = rfl::json::read<rfl::Generic>(good_string);
@@ -80,7 +47,7 @@ TEST(ubjson, test_decode_error_without_exception) {
8047
});
8148

8249
// A proposal: A generic prefix, followed by the underlying library's error output
83-
const std::string expected = R"(Could not parse ubjson: Unknown type at position 1)";
50+
const std::string expected = R"(Could not parse UBJSON: Unknown type at position 1)";
8451
EXPECT_EQ(result.error().what(), expected);
8552

8653
EXPECT_TRUE(!result.has_value() && true);

0 commit comments

Comments
 (0)