Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 29 additions & 17 deletions include/rfl/avro/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
#include <avro.h>

#include <ostream>
#include <stdexcept>
#include <type_traits>

#include "../parsing/Parent.hpp"
#include "Parser.hpp"
//#include "Schema.hpp"
#include "Writer.hpp"
#include "to_schema.hpp"

Expand All @@ -26,25 +26,37 @@ std::vector<char> write(const auto& _obj, const auto& _schema) {
int result = avro_generic_value_new(_schema.iface(), &root);
if (result != 0) {
avro_value_decref(&root);
throw std::runtime_error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
throw std::runtime_error(std::string(__FUNCTION__) + " error(" +
std::to_string(result) + "): " + avro_strerror());
}
const auto writer = Writer(&root);
Parser<T, Processors<Ps...>>::write(writer, _obj,
typename ParentType::Root{});
size_t size = 0;
result = avro_value_sizeof(&root, &size);
if (result != 0) {
throw std::runtime_error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
}
std::vector<char> buffer(size);
avro_writer_t avro_writer = avro_writer_memory(buffer.data(), buffer.size());
result = avro_value_write(avro_writer, &root);
if (result != 0) {
throw std::runtime_error(std::string(__FUNCTION__) + " error("+ std::to_string(result)+"): " + avro_strerror());
}
const auto buffer = [&]() -> Result<std::vector<char>> {
try {
Parser<T, Processors<Ps...>>::write(writer, _obj,
typename ParentType::Root{});
} catch (std::exception& e) {
return error(e.what());
}
size_t size = 0;
result = avro_value_sizeof(&root, &size);
if (result != 0) {
return error(std::string(__FUNCTION__) + " error(" +
std::to_string(result) + "): " + avro_strerror());
}
std::vector<char> buffer(size);
avro_writer_t avro_writer =
avro_writer_memory(buffer.data(), buffer.size());
result = avro_value_write(avro_writer, &root);
if (result != 0) {
avro_writer_free(avro_writer);
return error(std::string(__FUNCTION__) + " error(" +
std::to_string(result) + "): " + avro_strerror());
}
avro_writer_free(avro_writer);
return buffer;
}();
avro_value_decref(&root);
avro_writer_free(avro_writer);
return buffer;
return buffer.value();
}

/// Returns AVRO bytes.
Expand Down
27 changes: 7 additions & 20 deletions include/rfl/bson/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
#include <string>
#include <type_traits>

#include "../Bytestring.hpp"
#include "../Result.hpp"
#include "../Vectorstring.hpp"
#include "../always_false.hpp"
#include "../concepts.hpp"
#include "../internal/ptr_cast.hpp"

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

} else if constexpr (std::is_same<std::remove_cvref_t<T>,
rfl::Bytestring>() ||
std::is_same<std::remove_cvref_t<T>,
rfl::Vectorstring>()) {
} else if constexpr (concepts::MutableContiguousByteContainer<
std::remove_cvref_t<T>>) {
using VectorType = std::remove_cvref_t<T>;
using ValueType = typename VectorType::value_type;
if (btype != BSON_TYPE_BINARY) {
if constexpr (std::is_same<std::remove_cvref_t<T>, rfl::Bytestring>()) {
return error("Could not cast to bytestring.");
} else {
return error("Could not cast to vectorstring.");
}
return error("Could not cast to bytestring.");
}
if (value.v_binary.subtype != BSON_SUBTYPE_BINARY) {
if constexpr (std::is_same<std::remove_cvref_t<T>, rfl::Bytestring>()) {
return error(
"The BSON subtype must be a binary in order to read into a "
"bytestring.");
} else {
return error(
"The BSON subtype must be a binary in order to read into a "
"vectorstring.");
}
return error(
"The BSON subtype must be a binary in order to read into a "
"bytestring.");
}
const auto data =
internal::ptr_cast<const ValueType*>(value.v_binary.data);
Expand Down
149 changes: 99 additions & 50 deletions include/rfl/bson/Writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@
#include <bson/bson.h>

#include <cstddef>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <variant>
#include <vector>

#include "../Box.hpp"
#include "../Bytestring.hpp"
#include "../Ref.hpp"
//#include "../Result.hpp"
#include "../Vectorstring.hpp"
#include "../always_false.hpp"
#include "../internal/ptr_cast.hpp"
#include "../common.hpp"
#include "../concepts.hpp"
#include "../internal/ptr_cast.hpp"

namespace rfl {
namespace bson {
Expand Down Expand Up @@ -79,43 +78,65 @@ class RFL_API Writer {
}

OutputArrayType add_array_to_array(const size_t _size,
OutputArrayType* _parent) const noexcept;
OutputArrayType* _parent) const;

OutputArrayType add_array_to_object(const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const noexcept;
OutputObjectType* _parent) const;

OutputObjectType add_object_to_array(const size_t _size,
OutputArrayType* _parent) const noexcept;
OutputArrayType* _parent) const;

OutputObjectType add_object_to_object(
const std::string_view& _name, const size_t _size,
OutputObjectType* _parent) const noexcept;
OutputObjectType add_object_to_object(const std::string_view& _name,
const size_t _size,
OutputObjectType* _parent) const;

template <class T>
OutputVarType add_value_to_array(const T& _var,
OutputArrayType* _parent) const noexcept {
OutputArrayType* _parent) const {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
bson_array_builder_append_utf8(_parent->val_, _var.c_str(),
static_cast<int>(_var.size()));
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
rfl::Bytestring>() ||
std::is_same<std::remove_cvref_t<T>,
rfl::Vectorstring>()) {
bson_array_builder_append_binary(
const bool ok = bson_array_builder_append_utf8(
_parent->val_, _var.c_str(), static_cast<int>(_var.size()));
if (!ok) {
throw std::runtime_error("Could not append utf-8 to array.");
}

} else if constexpr (concepts::MutableContiguousByteContainer<
std::remove_cvref_t<T>>) {
const bool ok = bson_array_builder_append_binary(
_parent->val_, BSON_SUBTYPE_BINARY,
internal::ptr_cast<const uint8_t*>(_var.data()),
static_cast<uint32_t>(_var.size()));
if (!ok) {
throw std::runtime_error("Could not append binary to array.");
}

} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
bson_array_builder_append_bool(_parent->val_, _var);
const bool ok = bson_array_builder_append_bool(_parent->val_, _var);
if (!ok) {
throw std::runtime_error("Could not append bool to array.");
}

} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
bson_array_builder_append_double(_parent->val_,
static_cast<double>(_var));
const bool ok = bson_array_builder_append_double(
_parent->val_, static_cast<double>(_var));
if (!ok) {
throw std::runtime_error("Could not append float to array.");
}

} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
bson_array_builder_append_int64(_parent->val_,
static_cast<std::int64_t>(_var));
const bool ok = bson_array_builder_append_int64(
_parent->val_, static_cast<std::int64_t>(_var));
if (!ok) {
throw std::runtime_error("Could not append integer to array.");
}

} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>()) {
bson_array_builder_append_oid(_parent->val_, &_var);
const bool ok = bson_array_builder_append_oid(_parent->val_, &_var);
if (!ok) {
throw std::runtime_error("Could not append OID to array.");
}

} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
Expand All @@ -125,47 +146,75 @@ class RFL_API Writer {
template <class T>
OutputVarType add_value_to_object(const std::string_view& _name,
const T& _var,
OutputObjectType* _parent) const noexcept {
OutputObjectType* _parent) const {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
bson_append_utf8(_parent->val_, _name.data(),
static_cast<int>(_name.size()), _var.c_str(),
static_cast<int>(_var.size()));
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
rfl::Bytestring>() ||
std::is_same<std::remove_cvref_t<T>,
rfl::Vectorstring>()) {
bson_append_binary(_parent->val_, _name.data(),
static_cast<int>(_name.size()), BSON_SUBTYPE_BINARY,
internal::ptr_cast<const uint8_t*>(_var.data()),
static_cast<uint32_t>(_var.size()));
const bool ok = bson_append_utf8(
_parent->val_, _name.data(), static_cast<int>(_name.size()),
_var.c_str(), static_cast<int>(_var.size()));
if (!ok) {
throw std::runtime_error("Could not utf-8 field '" +
std::string(_name) + "' to object.");
}

} else if constexpr (concepts::MutableContiguousByteContainer<
std::remove_cvref_t<T>>) {
const bool ok = bson_append_binary(
_parent->val_, _name.data(), static_cast<int>(_name.size()),
BSON_SUBTYPE_BINARY, internal::ptr_cast<const uint8_t*>(_var.data()),
static_cast<uint32_t>(_var.size()));
if (!ok) {
throw std::runtime_error("Could not binary field '" +
std::string(_name) + "' to object.");
}

} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
bson_append_bool(_parent->val_, _name.data(),
static_cast<int>(_name.size()), _var);
const bool ok = bson_append_bool(_parent->val_, _name.data(),
static_cast<int>(_name.size()), _var);
if (!ok) {
throw std::runtime_error("Could not boolean field '" +
std::string(_name) + "' to object.");
}

} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
bson_append_double(_parent->val_, _name.data(),
static_cast<int>(_name.size()),
static_cast<double>(_var));
const bool ok = bson_append_double(_parent->val_, _name.data(),
static_cast<int>(_name.size()),
static_cast<double>(_var));
if (!ok) {
throw std::runtime_error("Could not floating point field '" +
std::string(_name) + "' to object.");
}

} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
bson_append_int64(_parent->val_, _name.data(),
static_cast<int>(_name.size()),
static_cast<std::int64_t>(_var));
const bool ok = bson_append_int64(_parent->val_, _name.data(),
static_cast<int>(_name.size()),
static_cast<std::int64_t>(_var));
if (!ok) {
throw std::runtime_error("Could not int field '" + std::string(_name) +
"' to object.");
}

} else if constexpr (std::is_same<std::remove_cvref_t<T>, bson_oid_t>()) {
bson_append_oid(_parent->val_, _name.data(),
static_cast<int>(_name.size()), &_var);
const bool ok = bson_append_oid(_parent->val_, _name.data(),
static_cast<int>(_name.size()), &_var);
if (!ok) {
throw std::runtime_error("Could not oid field '" + std::string(_name) +
"' to object.");
}

} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
return OutputVarType{};
}

OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept;
OutputVarType add_null_to_array(OutputArrayType* _parent) const;

OutputVarType add_null_to_object(const std::string_view& _name,
OutputObjectType* _parent) const noexcept;
OutputObjectType* _parent) const;

void end_array(OutputArrayType* _arr) const noexcept;
void end_array(OutputArrayType* _arr) const;

void end_object(OutputObjectType* _obj) const noexcept;
void end_object(OutputObjectType* _obj) const;

private:
/// Pointer to the main document. In BSON, documents are what are usually
Expand Down
Loading
Loading