Skip to content

Commit 2dec03b

Browse files
Added exceptions to BSON
1 parent 5c51824 commit 2dec03b

4 files changed

Lines changed: 169 additions & 82 deletions

File tree

include/rfl/bson/Reader.hpp

Lines changed: 3 additions & 6 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,10 +101,8 @@ 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) {

include/rfl/bson/Writer.hpp

Lines changed: 98 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@
1111
#include <vector>
1212

1313
#include "../Box.hpp"
14-
#include "../Bytestring.hpp"
1514
#include "../Ref.hpp"
16-
//#include "../Result.hpp"
17-
#include "../Vectorstring.hpp"
1815
#include "../always_false.hpp"
19-
#include "../internal/ptr_cast.hpp"
2016
#include "../common.hpp"
17+
#include "../concepts.hpp"
18+
#include "../internal/ptr_cast.hpp"
2119

2220
namespace rfl {
2321
namespace bson {
@@ -79,43 +77,65 @@ class RFL_API Writer {
7977
}
8078

8179
OutputArrayType add_array_to_array(const size_t _size,
82-
OutputArrayType* _parent) const noexcept;
80+
OutputArrayType* _parent) const;
8381

8482
OutputArrayType add_array_to_object(const std::string_view& _name,
8583
const size_t _size,
86-
OutputObjectType* _parent) const noexcept;
84+
OutputObjectType* _parent) const;
8785

8886
OutputObjectType add_object_to_array(const size_t _size,
89-
OutputArrayType* _parent) const noexcept;
87+
OutputArrayType* _parent) const;
9088

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

9593
template <class T>
9694
OutputVarType add_value_to_array(const T& _var,
97-
OutputArrayType* _parent) const noexcept {
95+
OutputArrayType* _parent) const {
9896
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(
97+
const bool ok = bson_array_builder_append_utf8(
98+
_parent->val_, _var.c_str(), static_cast<int>(_var.size()));
99+
if (!ok) {
100+
throw std::runtime_error("Could not append utf-8 to array.");
101+
}
102+
103+
} else if constexpr (concepts::MutableContiguousByteContainer<
104+
std::remove_cvref_t<T>>) {
105+
const bool ok = bson_array_builder_append_binary(
106106
_parent->val_, BSON_SUBTYPE_BINARY,
107107
internal::ptr_cast<const uint8_t*>(_var.data()),
108108
static_cast<uint32_t>(_var.size()));
109+
if (!ok) {
110+
throw std::runtime_error("Could not append binary to array.");
111+
}
112+
109113
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
110-
bson_array_builder_append_bool(_parent->val_, _var);
114+
const bool ok = bson_array_builder_append_bool(_parent->val_, _var);
115+
if (!ok) {
116+
throw std::runtime_error("Could not append bool to array.");
117+
}
118+
111119
} 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));
120+
const bool ok = bson_array_builder_append_double(
121+
_parent->val_, static_cast<double>(_var));
122+
if (!ok) {
123+
throw std::runtime_error("Could not append float to array.");
124+
}
125+
114126
} 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));
127+
const bool ok = bson_array_builder_append_int64(
128+
_parent->val_, static_cast<std::int64_t>(_var));
129+
if (!ok) {
130+
throw std::runtime_error("Could not append integer to array.");
131+
}
132+
117133
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>()) {
118-
bson_array_builder_append_oid(_parent->val_, &_var);
134+
const bool ok = bson_array_builder_append_oid(_parent->val_, &_var);
135+
if (!ok) {
136+
throw std::runtime_error("Could not append OID to array.");
137+
}
138+
119139
} else {
120140
static_assert(rfl::always_false_v<T>, "Unsupported type.");
121141
}
@@ -125,47 +145,75 @@ class RFL_API Writer {
125145
template <class T>
126146
OutputVarType add_value_to_object(const std::string_view& _name,
127147
const T& _var,
128-
OutputObjectType* _parent) const noexcept {
148+
OutputObjectType* _parent) const {
129149
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()));
150+
const bool ok = bson_append_utf8(
151+
_parent->val_, _name.data(), static_cast<int>(_name.size()),
152+
_var.c_str(), static_cast<int>(_var.size()));
153+
if (!ok) {
154+
throw std::runtime_error("Could not utf-8 field '" +
155+
std::string(_name) + "' to object.");
156+
}
157+
158+
} else if constexpr (concepts::MutableContiguousByteContainer<
159+
std::remove_cvref_t<T>>) {
160+
const bool ok = bson_append_binary(
161+
_parent->val_, _name.data(), static_cast<int>(_name.size()),
162+
BSON_SUBTYPE_BINARY, internal::ptr_cast<const uint8_t*>(_var.data()),
163+
static_cast<uint32_t>(_var.size()));
164+
if (!ok) {
165+
throw std::runtime_error("Could not binary field '" +
166+
std::string(_name) + "' to object.");
167+
}
168+
141169
} 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);
170+
const bool ok = bson_append_bool(_parent->val_, _name.data(),
171+
static_cast<int>(_name.size()), _var);
172+
if (!ok) {
173+
throw std::runtime_error("Could not boolean field '" +
174+
std::string(_name) + "' to object.");
175+
}
176+
144177
} 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));
178+
const bool ok = bson_append_double(_parent->val_, _name.data(),
179+
static_cast<int>(_name.size()),
180+
static_cast<double>(_var));
181+
if (!ok) {
182+
throw std::runtime_error("Could not floating point field '" +
183+
std::string(_name) + "' to object.");
184+
}
185+
148186
} 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));
187+
const bool ok = bson_append_int64(_parent->val_, _name.data(),
188+
static_cast<int>(_name.size()),
189+
static_cast<std::int64_t>(_var));
190+
if (!ok) {
191+
throw std::runtime_error("Could not int field '" + std::string(_name) +
192+
"' to object.");
193+
}
194+
152195
} 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);
196+
const bool ok = bson_append_oid(_parent->val_, _name.data(),
197+
static_cast<int>(_name.size()), &_var);
198+
if (!ok) {
199+
throw std::runtime_error("Could not oid field '" + std::string(_name) +
200+
"' to object.");
201+
}
202+
155203
} else {
156204
static_assert(rfl::always_false_v<T>, "Unsupported type.");
157205
}
158206
return OutputVarType{};
159207
}
160208

161-
OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept;
209+
OutputVarType add_null_to_array(OutputArrayType* _parent) const;
162210

163211
OutputVarType add_null_to_object(const std::string_view& _name,
164-
OutputObjectType* _parent) const noexcept;
212+
OutputObjectType* _parent) const;
165213

166-
void end_array(OutputArrayType* _arr) const noexcept;
214+
void end_array(OutputArrayType* _arr) const;
167215

168-
void end_object(OutputObjectType* _obj) const noexcept;
216+
void end_object(OutputObjectType* _obj) const;
169217

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

include/rfl/bson/write.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace bson {
1717
/// Returns BSON bytes. Careful: It is the responsibility of the caller to call
1818
/// bson_free on the returned pointer.
1919
template <class... Ps>
20-
std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
20+
std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) {
2121
using T = std::remove_cvref_t<decltype(_obj)>;
2222
using ParentType = parsing::Parent<Writer>;
2323
bson_t* doc = nullptr;
@@ -41,7 +41,7 @@ std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
4141

4242
/// Returns BSON bytes.
4343
template <class... Ps>
44-
std::vector<char> write(const auto& _obj) noexcept {
44+
std::vector<char> write(const auto& _obj) {
4545
auto [buf, len] = to_buffer<Ps...>(_obj);
4646
const auto result = std::vector<char>(internal::ptr_cast<char*>(buf),
4747
internal::ptr_cast<char*>(buf) + len);
@@ -51,7 +51,7 @@ std::vector<char> write(const auto& _obj) noexcept {
5151

5252
/// Writes a BSON into an ostream.
5353
template <class... Ps>
54-
std::ostream& write(const auto& _obj, std::ostream& _stream) noexcept {
54+
std::ostream& write(const auto& _obj, std::ostream& _stream) {
5555
auto [buf, len] = to_buffer<Ps...>(_obj);
5656
_stream.write(internal::ptr_cast<const char*>(buf), len);
5757
bson_free(buf);

src/rfl/bson/Writer.cpp

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,74 +23,116 @@ Writer::OutputVarType Writer::null_as_root() const noexcept {
2323
}
2424

2525
Writer::OutputArrayType Writer::add_array_to_array(
26-
const size_t /*_size*/, OutputArrayType* _parent) const noexcept {
26+
const size_t /*_size*/, OutputArrayType* _parent) const {
2727
bson_array_builder_t* val;
28-
bson_array_builder_append_array_builder_begin(_parent->val_, &val);
28+
const bool ok =
29+
bson_array_builder_append_array_builder_begin(_parent->val_, &val);
30+
if (!ok) {
31+
throw std::runtime_error("Could not array to array.");
32+
}
2933
return OutputArrayType(val, IsArray{_parent->val_});
3034
}
3135

3236
Writer::OutputArrayType Writer::add_array_to_object(
3337
const std::string_view& _name, const size_t /*_size*/,
34-
OutputObjectType* _parent) const noexcept {
38+
OutputObjectType* _parent) const {
3539
bson_array_builder_t* val;
36-
bson_append_array_builder_begin(_parent->val_, _name.data(),
37-
static_cast<int>(_name.size()), &val);
40+
const bool ok = bson_append_array_builder_begin(
41+
_parent->val_, _name.data(), static_cast<int>(_name.size()), &val);
42+
if (!ok) {
43+
throw std::runtime_error("Could not array to array.");
44+
}
3845
return OutputArrayType(val, IsObject{_parent->val_});
3946
}
4047

4148
Writer::OutputObjectType Writer::add_object_to_array(
42-
const size_t /*_size*/, OutputArrayType* _parent) const noexcept {
49+
const size_t /*_size*/, OutputArrayType* _parent) const {
4350
subdocs_->emplace_back(rfl::Box<BSONType>());
44-
bson_array_builder_append_document_begin(_parent->val_,
45-
&(subdocs_->back()->val_));
51+
const bool ok = bson_array_builder_append_document_begin(
52+
_parent->val_, &(subdocs_->back()->val_));
53+
if (!ok) {
54+
throw std::runtime_error("Could not object to array.");
55+
}
4656
return OutputObjectType(&subdocs_->back()->val_, IsArray{_parent->val_});
4757
}
4858

4959
Writer::OutputObjectType Writer::add_object_to_object(
5060
const std::string_view& _name, const size_t /*_size*/,
51-
OutputObjectType* _parent) const noexcept {
61+
OutputObjectType* _parent) const {
5262
subdocs_->emplace_back(rfl::Box<BSONType>());
53-
bson_append_document_begin(_parent->val_, _name.data(),
54-
static_cast<int>(_name.size()),
55-
&(subdocs_->back()->val_));
63+
const bool ok = bson_append_document_begin(_parent->val_, _name.data(),
64+
static_cast<int>(_name.size()),
65+
&(subdocs_->back()->val_));
66+
if (!ok) {
67+
throw std::runtime_error("Could not add object to object.");
68+
}
5669
return OutputObjectType(&subdocs_->back()->val_, IsObject{_parent->val_});
5770
}
5871

5972
Writer::OutputVarType Writer::add_null_to_array(
60-
OutputArrayType* _parent) const noexcept {
61-
bson_array_builder_append_null(_parent->val_);
73+
OutputArrayType* _parent) const {
74+
const bool ok = bson_array_builder_append_null(_parent->val_);
75+
if (!ok) {
76+
throw std::runtime_error("Could not add null to array.");
77+
}
6278
return OutputVarType{};
6379
}
6480

6581
Writer::OutputVarType Writer::add_null_to_object(
66-
const std::string_view& _name, OutputObjectType* _parent) const noexcept {
67-
bson_append_null(_parent->val_, _name.data(), static_cast<int>(_name.size()));
82+
const std::string_view& _name, OutputObjectType* _parent) const {
83+
const bool ok = bson_append_null(_parent->val_, _name.data(),
84+
static_cast<int>(_name.size()));
85+
if (!ok) {
86+
throw std::runtime_error("Could not add null to object.");
87+
}
6888
return OutputVarType{};
6989
}
7090

71-
void Writer::end_array(OutputArrayType* _arr) const noexcept {
91+
void Writer::end_array(OutputArrayType* _arr) const {
7292
const auto handle = [&](const auto _parent) {
7393
using Type = std::remove_cvref_t<decltype(_parent)>;
7494
if constexpr (std::is_same<Type, IsArray>()) {
75-
bson_array_builder_append_array_builder_end(_parent.ptr_, _arr->val_);
95+
const bool ok =
96+
bson_array_builder_append_array_builder_end(_parent.ptr_, _arr->val_);
97+
if (!ok) {
98+
throw std::runtime_error("Could not end array.");
99+
}
100+
76101
} else if constexpr (std::is_same<Type, IsObject>()) {
77-
bson_append_array_builder_end(_parent.ptr_, _arr->val_);
102+
const bool ok = bson_append_array_builder_end(_parent.ptr_, _arr->val_);
103+
if (!ok) {
104+
throw std::runtime_error("Could not end array.");
105+
}
106+
78107
} else if constexpr (std::is_same<Type, IsRoot>()) {
79-
bson_array_builder_build(_arr->val_, doc_);
108+
const bool ok = bson_array_builder_build(_arr->val_, doc_);
109+
if (!ok) {
110+
throw std::runtime_error("Could not end array.");
111+
}
112+
80113
} else {
81114
static_assert(rfl::always_false_v<Type>, "Unsupported type.");
82115
}
83116
};
84117
std::visit(handle, _arr->parent_);
85118
}
86119

87-
void Writer::end_object(OutputObjectType* _obj) const noexcept {
120+
void Writer::end_object(OutputObjectType* _obj) const {
88121
const auto handle = [&](const auto _parent) {
89122
using Type = std::remove_cvref_t<decltype(_parent)>;
90123
if constexpr (std::is_same<Type, IsArray>()) {
91-
bson_array_builder_append_document_end(_parent.ptr_, _obj->val_);
124+
const bool ok =
125+
bson_array_builder_append_document_end(_parent.ptr_, _obj->val_);
126+
if (!ok) {
127+
throw std::runtime_error("Could not end object.");
128+
}
129+
92130
} else if constexpr (std::is_same<Type, IsObject>()) {
93-
bson_append_document_end(_parent.ptr_, _obj->val_);
131+
const bool ok = bson_append_document_end(_parent.ptr_, _obj->val_);
132+
if (!ok) {
133+
throw std::runtime_error("Could not end object.");
134+
}
135+
94136
} else if constexpr (std::is_same<Type, IsRoot>()) {
95137
} else {
96138
static_assert(rfl::always_false_v<Type>, "Unsupported type.");

0 commit comments

Comments
 (0)