Skip to content

Commit 3ae6833

Browse files
Make sure avro ints and floats are always written properly; fixes #522 (#532)
1 parent d0f60b2 commit 3ae6833

File tree

72 files changed

+346
-289
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+346
-289
lines changed

include/rfl/avro/Parser.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ template <class ProcessorsType>
4848
requires AreReaderAndWriter<avro::Reader, avro::Writer, Generic>
4949
struct Parser<avro::Reader, avro::Writer, Generic, ProcessorsType> {
5050
template <class T>
51-
static Result<Generic> read(const avro::Reader&, const T&) noexcept {
51+
static Result<Generic> read(const avro::Reader&, const T&) {
5252
static_assert(always_false_v<T>, "Generics are unsupported in Avro.");
5353
return error("Unsupported");
5454
}
5555

5656
template <class P>
57-
static void write(const avro::Writer&, const Generic&, const P&) noexcept {
57+
static void write(const avro::Writer&, const Generic&, const P&) {
5858
static_assert(always_false_v<P>, "Generics are unsupported in Avro.");
5959
}
6060

@@ -78,7 +78,7 @@ struct Parser<avro::Reader, avro::Writer,
7878

7979
template <class U>
8080
static Result<internal::Skip<T, _skip_serialization, _skip_deserialization>>
81-
read(const R&, const U&) noexcept {
81+
read(const R&, const U&) {
8282
static_assert(always_false_v<T>, "rfl::Skip is unsupported in Avro.");
8383
return Error("Unsupported");
8484
}
@@ -87,7 +87,7 @@ struct Parser<avro::Reader, avro::Writer,
8787
static void write(const W& /*_w*/,
8888
const internal::Skip<T, _skip_serialization,
8989
_skip_deserialization>& /*_skip*/,
90-
const P& /*_parent*/) noexcept {
90+
const P& /*_parent*/) {
9191
static_assert(always_false_v<P>, "rfl::Skip is unsupported in Avro.");
9292
}
9393

include/rfl/avro/Reader.hpp

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
#include <string_view>
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/is_literal.hpp"
1716
#include "../parsing/schemaful/IsSchemafulReader.hpp"
1817

@@ -67,22 +66,15 @@ struct Reader {
6766
return std::string("");
6867
}
6968
return std::string(c_str, size - 1);
70-
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
71-
rfl::Bytestring>() ||
72-
std::is_same<std::remove_cvref_t<T>,
73-
rfl::Vectorstring>()) {
69+
} else if constexpr (concepts::MutableContiguousByteContainer<
70+
std::remove_cvref_t<T>>) {
7471
using VectorType = std::remove_cvref_t<T>;
7572
using ValueType = typename VectorType::value_type;
7673
const void* ptr = nullptr;
7774
size_t size = 0;
7875
const auto err = avro_value_get_bytes(_var.val_, &ptr, &size);
7976
if (err) {
80-
if constexpr (std::is_same<std::remove_cvref_t<T>,
81-
rfl::Bytestring>()) {
82-
return error("Could not cast to bytestring.");
83-
} else {
84-
return error("Could not cast to vectorstring.");
85-
}
77+
return error("Could not cast to bytestring.");
8678
}
8779
const auto data = internal::ptr_cast<const ValueType*>(ptr);
8880
return VectorType(data, data + size);
@@ -93,7 +85,8 @@ struct Reader {
9385
int result_value = 0;
9486
int result = avro_value_get_boolean(_var.val_, &result_value);
9587
if (result != 0) {
96-
return error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
88+
return error(std::string(__FUNCTION__) + " error(" +
89+
std::to_string(result) + "): " + avro_strerror());
9790
}
9891
return (result_value != 0);
9992

@@ -191,16 +184,16 @@ struct Reader {
191184
const InputArrayType& _arr) const noexcept {
192185
size_t size = 0;
193186
int res = avro_value_get_size(_arr.val_, &size);
194-
if(res)
195-
{
196-
return Error(std::string(__FUNCTION__) + " error(" + std::to_string(res) + "): " + avro_strerror());
187+
if (res) {
188+
return Error(std::string(__FUNCTION__) + " error(" + std::to_string(res) +
189+
"): " + avro_strerror());
197190
}
198191
for (size_t ix = 0; ix < size; ++ix) {
199192
avro_value_t element;
200193
res = avro_value_get_by_index(_arr.val_, ix, &element, nullptr);
201-
if(res)
202-
{
203-
return Error(std::string(__FUNCTION__) + " error(" + std::to_string(res) + "): " + avro_strerror());
194+
if (res) {
195+
return Error(std::string(__FUNCTION__) + " error(" +
196+
std::to_string(res) + "): " + avro_strerror());
204197
}
205198
const auto err = _array_reader.read(InputVarType{&element});
206199
if (err) {
@@ -215,17 +208,17 @@ struct Reader {
215208
const InputMapType& _map) const noexcept {
216209
size_t size = 0;
217210
int res = avro_value_get_size(_map.val_, &size);
218-
if(res!=0)
219-
{
220-
return Error(std::string(__FUNCTION__) + " error("+ std::to_string(res)+"): " + avro_strerror());
211+
if (res != 0) {
212+
return Error(std::string(__FUNCTION__) + " error(" + std::to_string(res) +
213+
"): " + avro_strerror());
221214
}
222215
for (size_t ix = 0; ix < size; ++ix) {
223216
avro_value_t element;
224217
const char* key = nullptr;
225218
res = avro_value_get_by_index(_map.val_, ix, &element, &key);
226-
if(res!=0)
227-
{
228-
return Error(std::string(__FUNCTION__) + " error("+ std::to_string(res)+"): " + avro_strerror());
219+
if (res != 0) {
220+
return Error(std::string(__FUNCTION__) + " error(" +
221+
std::to_string(res) + "): " + avro_strerror());
229222
}
230223
_map_reader.read(std::string_view(key), InputVarType{&element});
231224
}
@@ -237,16 +230,16 @@ struct Reader {
237230
const InputObjectType& _obj) const noexcept {
238231
size_t size = 0;
239232
int res = avro_value_get_size(_obj.val_, &size);
240-
if(res!=0)
241-
{
242-
return Error(std::string(__FUNCTION__) + " error("+ std::to_string(res)+"): " + avro_strerror());
233+
if (res != 0) {
234+
return Error(std::string(__FUNCTION__) + " error(" + std::to_string(res) +
235+
"): " + avro_strerror());
243236
}
244237
for (size_t ix = 0; ix < size; ++ix) {
245238
avro_value_t element;
246239
res = avro_value_get_by_index(_obj.val_, ix, &element, nullptr);
247-
if(res!=0)
248-
{
249-
return Error(std::string(__FUNCTION__) + " error("+ std::to_string(res)+"): " + avro_strerror());
240+
if (res != 0) {
241+
return Error(std::string(__FUNCTION__) + " error(" +
242+
std::to_string(res) + "): " + avro_strerror());
250243
}
251244
_object_reader.read(static_cast<int>(ix), InputVarType{&element});
252245
}

include/rfl/avro/Writer.hpp

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,15 @@
55

66
#include <climits>
77
#include <cstdint>
8+
#include <stdexcept>
89
#include <string>
910
#include <string_view>
1011
#include <type_traits>
1112

12-
#include "../Bytestring.hpp"
13-
#include "../Timestamp.hpp"
14-
#include "../Vectorstring.hpp"
1513
#include "../always_false.hpp"
1614
#include "../common.hpp"
15+
#include "../concepts.hpp"
1716
#include "../internal/is_literal.hpp"
18-
#include "../internal/is_validator.hpp"
19-
#include "../patterns.hpp"
2017

2118
namespace rfl::avro {
2219

@@ -52,15 +49,15 @@ class RFL_API Writer {
5249

5350
~Writer();
5451

55-
OutputArrayType array_as_root(const size_t _size) const noexcept;
52+
OutputArrayType array_as_root(const size_t _size) const;
5653

57-
OutputMapType map_as_root(const size_t _size) const noexcept;
54+
OutputMapType map_as_root(const size_t _size) const;
5855

59-
OutputObjectType object_as_root(const size_t _size) const noexcept;
56+
OutputObjectType object_as_root(const size_t _size) const;
6057

6158
OutputVarType null_as_root() const;
6259

63-
OutputUnionType union_as_root() const noexcept;
60+
OutputUnionType union_as_root() const;
6461

6562
template <class T>
6663
OutputVarType value_as_root(const T& _var) const {
@@ -138,7 +135,7 @@ class RFL_API Writer {
138135
avro_value_t new_value;
139136
int result = avro_value_append(&_parent->val_, &new_value, nullptr);
140137
if (result != 0) {
141-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
138+
throw std::runtime_error("Error adding value to array: error(" +
142139
std::to_string(result) +
143140
"): " + avro_strerror());
144141
}
@@ -153,7 +150,7 @@ class RFL_API Writer {
153150
int result = avro_value_add(&_parent->val_, _name.data(), &new_value,
154151
nullptr, nullptr);
155152
if (result != 0) {
156-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
153+
throw std::runtime_error("Error adding value to map: error(" +
157154
std::to_string(result) +
158155
"): " + avro_strerror());
159156
}
@@ -169,7 +166,7 @@ class RFL_API Writer {
169166
int result = avro_value_get_by_name(&_parent->val_, _name.data(),
170167
&new_value, nullptr);
171168
if (result != 0) {
172-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
169+
throw std::runtime_error("Error adding value to object: error(" +
173170
std::to_string(result) +
174171
"): " + avro_strerror());
175172
}
@@ -181,13 +178,13 @@ class RFL_API Writer {
181178
OutputVarType add_value_to_union(const size_t _index, const T& _var,
182179
OutputUnionType* _parent) const {
183180
if (_index > static_cast<size_t>(INT_MAX)) {
184-
throw std::runtime_error(std::string(__FUNCTION__) + " index error");
181+
throw std::runtime_error("Error adding value to unions: Index error");
185182
}
186183
avro_value_t new_value;
187184
int result = avro_value_set_branch(&_parent->val_, static_cast<int>(_index),
188185
&new_value);
189186
if (result != 0) {
190-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
187+
throw std::runtime_error("Error adding value to union: error(" +
191188
std::to_string(result) +
192189
"): " + avro_strerror());
193190
}
@@ -204,67 +201,79 @@ class RFL_API Writer {
204201
private:
205202
template <class T>
206203
void set_value(const T& _var, avro_value_t* _val) const {
207-
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
204+
using Type = std::remove_cvref_t<T>;
205+
206+
if constexpr (std::is_same_v<Type, std::string>) {
208207
int result =
209208
avro_value_set_string_len(_val, _var.c_str(), _var.size() + 1);
210209
if (result != 0) {
211-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
212-
std::to_string(result) +
213-
"): " + avro_strerror());
210+
throw std::runtime_error(
211+
"Error setting string value: " + std::to_string(result) + ": " +
212+
avro_strerror());
214213
}
215-
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
216-
rfl::Bytestring>() ||
217-
std::is_same<std::remove_cvref_t<T>,
218-
rfl::Vectorstring>()) {
214+
215+
} else if constexpr (concepts::MutableContiguousByteContainer<Type>) {
219216
auto var = _var;
220217
if (!var.data()) {
221218
return;
222219
}
223220
int result = avro_value_set_bytes(_val, var.data(), var.size());
224221
if (result != 0) {
225-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
226-
std::to_string(result) +
227-
"): " + avro_strerror());
222+
throw std::runtime_error(
223+
"Error setting bytestring value: " + std::to_string(result) + ": " +
224+
avro_strerror());
228225
}
229-
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
226+
227+
} else if constexpr (std::is_same_v<Type, bool>) {
230228
int result = avro_value_set_boolean(_val, _var);
231229
if (result != 0) {
232-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
233-
std::to_string(result) +
234-
"): " + avro_strerror());
230+
throw std::runtime_error(
231+
"Error setting boolean value: " + std::to_string(result) + ": " +
232+
avro_strerror());
235233
}
236-
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
237-
/*int result = avro_value_set_double(_val, static_cast<double>(_var));
234+
235+
} else if constexpr (std::is_same_v<Type, float>) {
236+
int result = avro_value_set_float(_val, static_cast<float>(_var));
238237
if (result != 0) {
239-
throw std::runtime_error(std::string(__FUNCTION__) + " error("+
240-
std::to_string(result)+"): " + avro_strerror());
241-
}*/
242-
avro_value_set_double(_val, static_cast<double>(_var));
243-
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
244-
/*int result = avro_value_set_long(_val, static_cast<std::int64_t>(_var));
238+
throw std::runtime_error(
239+
"Error setting float value: " + std::to_string(result) + ": " +
240+
avro_strerror());
241+
}
242+
243+
} else if constexpr (std::is_floating_point_v<Type>) {
244+
int result = avro_value_set_double(_val, static_cast<double>(_var));
245245
if (result != 0) {
246-
throw std::runtime_error(std::string(__FUNCTION__) + " error("+
247-
std::to_string(result)+"): " + avro_strerror());
248-
}*/
249-
avro_value_set_long(_val, static_cast<std::int64_t>(_var));
246+
throw std::runtime_error(
247+
"Error setting double value: " + std::to_string(result) + ": " +
248+
avro_strerror());
249+
}
250+
251+
} else if constexpr (std::is_same_v<Type, std::int64_t> ||
252+
std::is_same_v<Type, std::uint32_t> ||
253+
std::is_same_v<Type, std::uint64_t>) {
254+
int result = avro_value_set_long(_val, static_cast<std::int64_t>(_var));
255+
if (result != 0) {
256+
throw std::runtime_error(
257+
"Error setting long value: " + std::to_string(result) + ": " +
258+
avro_strerror());
259+
}
260+
261+
} else if constexpr (std::is_integral_v<Type>) {
262+
int result = avro_value_set_int(_val, static_cast<std::int32_t>(_var));
263+
if (result != 0) {
264+
throw std::runtime_error(
265+
"Error setting int value: " + std::to_string(result) + ": " +
266+
avro_strerror());
267+
}
268+
250269
} else if constexpr (internal::is_literal_v<T>) {
251270
int result = avro_value_set_enum(_val, static_cast<int>(_var.value()));
252271
if (result != 0) {
253-
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
254-
std::to_string(result) +
255-
"): " + avro_strerror());
272+
throw std::runtime_error(
273+
"Error setting literal value: " + std::to_string(result) + ": " +
274+
avro_strerror());
256275
}
257-
} else if constexpr (internal::is_validator_v<T>) {
258-
using ValueType = std::remove_cvref_t<typename T::ReflectionType>;
259-
const auto val = _var.value();
260-
set_value<ValueType>(val, _val);
261-
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
262-
rfl::Timestamp<"%Y-%m-%d">>()) {
263-
const auto str = _var.to_string();
264-
set_value<std::string>(str, _val);
265-
} else if constexpr (std::is_same<std::remove_cvref_t<T>, rfl::Email>()) {
266-
const auto& str = static_cast<const std::string&>(_var);
267-
set_value<std::string>(str, _val);
276+
268277
} else {
269278
static_assert(rfl::always_false_v<T>, "Unsupported type.");
270279
}

include/rfl/avro/schema/Type.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <string>
77

88
#include "../../Literal.hpp"
9-
//#include "../../Object.hpp"
109
#include "../../Ref.hpp"
1110
#include "../../Rename.hpp"
1211
#include "../../Variant.hpp"
@@ -36,7 +35,7 @@ struct RFL_API Type {
3635
};
3736

3837
struct Double {
39-
Literal<"float"> type{};
38+
Literal<"double"> type{};
4039
};
4140

4241
struct Bytes {

include/rfl/avro/to_schema.hpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,12 @@
33

44
#include <string>
55

6-
//#include "../Literal.hpp"
76
#include "../Processors.hpp"
8-
//#include "../Variant.hpp"
9-
//#include "../json.hpp"
10-
//#include "../parsing/schema/Type.hpp"
11-
//#include "../parsing/schema/ValidationType.hpp"
7+
#include "../common.hpp"
128
#include "../parsing/schema/make.hpp"
139
#include "Reader.hpp"
1410
#include "Schema.hpp"
1511
#include "Writer.hpp"
16-
//#include "schema/Type.hpp"
17-
#include "../common.hpp"
1812

1913
namespace rfl::avro {
2014

0 commit comments

Comments
 (0)