Skip to content

Commit 2b1cd83

Browse files
Use exceptions inside the writers (#535)
Adds error handling using exceptions in the write processes.
1 parent 3ae6833 commit 2b1cd83

File tree

31 files changed

+873
-679
lines changed

31 files changed

+873
-679
lines changed

include/rfl/avro/write.hpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
#include <avro.h>
55

66
#include <ostream>
7+
#include <stdexcept>
78
#include <type_traits>
89

910
#include "../parsing/Parent.hpp"
1011
#include "Parser.hpp"
11-
//#include "Schema.hpp"
1212
#include "Writer.hpp"
1313
#include "to_schema.hpp"
1414

@@ -26,25 +26,37 @@ std::vector<char> write(const auto& _obj, const auto& _schema) {
2626
int result = avro_generic_value_new(_schema.iface(), &root);
2727
if (result != 0) {
2828
avro_value_decref(&root);
29-
throw std::runtime_error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
29+
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
30+
std::to_string(result) + "): " + avro_strerror());
3031
}
3132
const auto writer = Writer(&root);
32-
Parser<T, Processors<Ps...>>::write(writer, _obj,
33-
typename ParentType::Root{});
34-
size_t size = 0;
35-
result = avro_value_sizeof(&root, &size);
36-
if (result != 0) {
37-
throw std::runtime_error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
38-
}
39-
std::vector<char> buffer(size);
40-
avro_writer_t avro_writer = avro_writer_memory(buffer.data(), buffer.size());
41-
result = avro_value_write(avro_writer, &root);
42-
if (result != 0) {
43-
throw std::runtime_error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
44-
}
33+
const auto buffer = [&]() -> Result<std::vector<char>> {
34+
try {
35+
Parser<T, Processors<Ps...>>::write(writer, _obj,
36+
typename ParentType::Root{});
37+
} catch (std::exception& e) {
38+
return error(e.what());
39+
}
40+
size_t size = 0;
41+
result = avro_value_sizeof(&root, &size);
42+
if (result != 0) {
43+
return error(std::string(__FUNCTION__) + " error(" +
44+
std::to_string(result) + "): " + avro_strerror());
45+
}
46+
std::vector<char> buffer(size);
47+
avro_writer_t avro_writer =
48+
avro_writer_memory(buffer.data(), buffer.size());
49+
result = avro_value_write(avro_writer, &root);
50+
if (result != 0) {
51+
avro_writer_free(avro_writer);
52+
return error(std::string(__FUNCTION__) + " error(" +
53+
std::to_string(result) + "): " + avro_strerror());
54+
}
55+
avro_writer_free(avro_writer);
56+
return buffer;
57+
}();
4558
avro_value_decref(&root);
46-
avro_writer_free(avro_writer);
47-
return buffer;
59+
return buffer.value();
4860
}
4961

5062
/// Returns AVRO bytes.

include/rfl/bson/Reader.hpp

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
#include <string>
1010
#include <type_traits>
1111

12-
#include "../Bytestring.hpp"
1312
#include "../Result.hpp"
14-
#include "../Vectorstring.hpp"
1513
#include "../always_false.hpp"
14+
#include "../concepts.hpp"
1615
#include "../internal/ptr_cast.hpp"
1716

1817
namespace rfl {
@@ -102,29 +101,17 @@ struct Reader {
102101
"Could not cast to string. The type must be UTF8 or symbol.");
103102
}
104103

105-
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
106-
rfl::Bytestring>() ||
107-
std::is_same<std::remove_cvref_t<T>,
108-
rfl::Vectorstring>()) {
104+
} else if constexpr (concepts::MutableContiguousByteContainer<
105+
std::remove_cvref_t<T>>) {
109106
using VectorType = std::remove_cvref_t<T>;
110107
using ValueType = typename VectorType::value_type;
111108
if (btype != BSON_TYPE_BINARY) {
112-
if constexpr (std::is_same<std::remove_cvref_t<T>, rfl::Bytestring>()) {
113-
return error("Could not cast to bytestring.");
114-
} else {
115-
return error("Could not cast to vectorstring.");
116-
}
109+
return error("Could not cast to bytestring.");
117110
}
118111
if (value.v_binary.subtype != BSON_SUBTYPE_BINARY) {
119-
if constexpr (std::is_same<std::remove_cvref_t<T>, rfl::Bytestring>()) {
120-
return error(
121-
"The BSON subtype must be a binary in order to read into a "
122-
"bytestring.");
123-
} else {
124-
return error(
125-
"The BSON subtype must be a binary in order to read into a "
126-
"vectorstring.");
127-
}
112+
return error(
113+
"The BSON subtype must be a binary in order to read into a "
114+
"bytestring.");
128115
}
129116
const auto data =
130117
internal::ptr_cast<const ValueType*>(value.v_binary.data);

include/rfl/bson/Writer.hpp

Lines changed: 99 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,19 @@
44
#include <bson/bson.h>
55

66
#include <cstddef>
7+
#include <stdexcept>
78
#include <string>
89
#include <string_view>
910
#include <type_traits>
1011
#include <variant>
1112
#include <vector>
1213

1314
#include "../Box.hpp"
14-
#include "../Bytestring.hpp"
1515
#include "../Ref.hpp"
16-
//#include "../Result.hpp"
17-
#include "../Vectorstring.hpp"
1816
#include "../always_false.hpp"
19-
#include "../internal/ptr_cast.hpp"
2017
#include "../common.hpp"
18+
#include "../concepts.hpp"
19+
#include "../internal/ptr_cast.hpp"
2120

2221
namespace rfl {
2322
namespace bson {
@@ -79,43 +78,65 @@ class RFL_API Writer {
7978
}
8079

8180
OutputArrayType add_array_to_array(const size_t _size,
82-
OutputArrayType* _parent) const noexcept;
81+
OutputArrayType* _parent) const;
8382

8483
OutputArrayType add_array_to_object(const std::string_view& _name,
8584
const size_t _size,
86-
OutputObjectType* _parent) const noexcept;
85+
OutputObjectType* _parent) const;
8786

8887
OutputObjectType add_object_to_array(const size_t _size,
89-
OutputArrayType* _parent) const noexcept;
88+
OutputArrayType* _parent) const;
9089

91-
OutputObjectType add_object_to_object(
92-
const std::string_view& _name, const size_t _size,
93-
OutputObjectType* _parent) const noexcept;
90+
OutputObjectType add_object_to_object(const std::string_view& _name,
91+
const size_t _size,
92+
OutputObjectType* _parent) const;
9493

9594
template <class T>
9695
OutputVarType add_value_to_array(const T& _var,
97-
OutputArrayType* _parent) const noexcept {
96+
OutputArrayType* _parent) const {
9897
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
99-
bson_array_builder_append_utf8(_parent->val_, _var.c_str(),
100-
static_cast<int>(_var.size()));
101-
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
102-
rfl::Bytestring>() ||
103-
std::is_same<std::remove_cvref_t<T>,
104-
rfl::Vectorstring>()) {
105-
bson_array_builder_append_binary(
98+
const bool ok = bson_array_builder_append_utf8(
99+
_parent->val_, _var.c_str(), static_cast<int>(_var.size()));
100+
if (!ok) {
101+
throw std::runtime_error("Could not append utf-8 to array.");
102+
}
103+
104+
} else if constexpr (concepts::MutableContiguousByteContainer<
105+
std::remove_cvref_t<T>>) {
106+
const bool ok = bson_array_builder_append_binary(
106107
_parent->val_, BSON_SUBTYPE_BINARY,
107108
internal::ptr_cast<const uint8_t*>(_var.data()),
108109
static_cast<uint32_t>(_var.size()));
110+
if (!ok) {
111+
throw std::runtime_error("Could not append binary to array.");
112+
}
113+
109114
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
110-
bson_array_builder_append_bool(_parent->val_, _var);
115+
const bool ok = bson_array_builder_append_bool(_parent->val_, _var);
116+
if (!ok) {
117+
throw std::runtime_error("Could not append bool to array.");
118+
}
119+
111120
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
112-
bson_array_builder_append_double(_parent->val_,
113-
static_cast<double>(_var));
121+
const bool ok = bson_array_builder_append_double(
122+
_parent->val_, static_cast<double>(_var));
123+
if (!ok) {
124+
throw std::runtime_error("Could not append float to array.");
125+
}
126+
114127
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
115-
bson_array_builder_append_int64(_parent->val_,
116-
static_cast<std::int64_t>(_var));
128+
const bool ok = bson_array_builder_append_int64(
129+
_parent->val_, static_cast<std::int64_t>(_var));
130+
if (!ok) {
131+
throw std::runtime_error("Could not append integer to array.");
132+
}
133+
117134
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>()) {
118-
bson_array_builder_append_oid(_parent->val_, &_var);
135+
const bool ok = bson_array_builder_append_oid(_parent->val_, &_var);
136+
if (!ok) {
137+
throw std::runtime_error("Could not append OID to array.");
138+
}
139+
119140
} else {
120141
static_assert(rfl::always_false_v<T>, "Unsupported type.");
121142
}
@@ -125,47 +146,75 @@ class RFL_API Writer {
125146
template <class T>
126147
OutputVarType add_value_to_object(const std::string_view& _name,
127148
const T& _var,
128-
OutputObjectType* _parent) const noexcept {
149+
OutputObjectType* _parent) const {
129150
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
130-
bson_append_utf8(_parent->val_, _name.data(),
131-
static_cast<int>(_name.size()), _var.c_str(),
132-
static_cast<int>(_var.size()));
133-
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
134-
rfl::Bytestring>() ||
135-
std::is_same<std::remove_cvref_t<T>,
136-
rfl::Vectorstring>()) {
137-
bson_append_binary(_parent->val_, _name.data(),
138-
static_cast<int>(_name.size()), BSON_SUBTYPE_BINARY,
139-
internal::ptr_cast<const uint8_t*>(_var.data()),
140-
static_cast<uint32_t>(_var.size()));
151+
const bool ok = bson_append_utf8(
152+
_parent->val_, _name.data(), static_cast<int>(_name.size()),
153+
_var.c_str(), static_cast<int>(_var.size()));
154+
if (!ok) {
155+
throw std::runtime_error("Could not utf-8 field '" +
156+
std::string(_name) + "' to object.");
157+
}
158+
159+
} else if constexpr (concepts::MutableContiguousByteContainer<
160+
std::remove_cvref_t<T>>) {
161+
const bool ok = bson_append_binary(
162+
_parent->val_, _name.data(), static_cast<int>(_name.size()),
163+
BSON_SUBTYPE_BINARY, internal::ptr_cast<const uint8_t*>(_var.data()),
164+
static_cast<uint32_t>(_var.size()));
165+
if (!ok) {
166+
throw std::runtime_error("Could not binary field '" +
167+
std::string(_name) + "' to object.");
168+
}
169+
141170
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
142-
bson_append_bool(_parent->val_, _name.data(),
143-
static_cast<int>(_name.size()), _var);
171+
const bool ok = bson_append_bool(_parent->val_, _name.data(),
172+
static_cast<int>(_name.size()), _var);
173+
if (!ok) {
174+
throw std::runtime_error("Could not boolean field '" +
175+
std::string(_name) + "' to object.");
176+
}
177+
144178
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
145-
bson_append_double(_parent->val_, _name.data(),
146-
static_cast<int>(_name.size()),
147-
static_cast<double>(_var));
179+
const bool ok = bson_append_double(_parent->val_, _name.data(),
180+
static_cast<int>(_name.size()),
181+
static_cast<double>(_var));
182+
if (!ok) {
183+
throw std::runtime_error("Could not floating point field '" +
184+
std::string(_name) + "' to object.");
185+
}
186+
148187
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
149-
bson_append_int64(_parent->val_, _name.data(),
150-
static_cast<int>(_name.size()),
151-
static_cast<std::int64_t>(_var));
188+
const bool ok = bson_append_int64(_parent->val_, _name.data(),
189+
static_cast<int>(_name.size()),
190+
static_cast<std::int64_t>(_var));
191+
if (!ok) {
192+
throw std::runtime_error("Could not int field '" + std::string(_name) +
193+
"' to object.");
194+
}
195+
152196
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>()) {
153-
bson_append_oid(_parent->val_, _name.data(),
154-
static_cast<int>(_name.size()), &_var);
197+
const bool ok = bson_append_oid(_parent->val_, _name.data(),
198+
static_cast<int>(_name.size()), &_var);
199+
if (!ok) {
200+
throw std::runtime_error("Could not oid field '" + std::string(_name) +
201+
"' to object.");
202+
}
203+
155204
} else {
156205
static_assert(rfl::always_false_v<T>, "Unsupported type.");
157206
}
158207
return OutputVarType{};
159208
}
160209

161-
OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept;
210+
OutputVarType add_null_to_array(OutputArrayType* _parent) const;
162211

163212
OutputVarType add_null_to_object(const std::string_view& _name,
164-
OutputObjectType* _parent) const noexcept;
213+
OutputObjectType* _parent) const;
165214

166-
void end_array(OutputArrayType* _arr) const noexcept;
215+
void end_array(OutputArrayType* _arr) const;
167216

168-
void end_object(OutputObjectType* _obj) const noexcept;
217+
void end_object(OutputObjectType* _obj) const;
169218

170219
private:
171220
/// Pointer to the main document. In BSON, documents are what are usually

0 commit comments

Comments
 (0)