Skip to content

Commit

Permalink
Began implementing the BSON writer
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzicheng1987 committed Jan 13, 2024
1 parent e6b76a7 commit ee3981d
Showing 1 changed file with 102 additions and 85 deletions.
187 changes: 102 additions & 85 deletions include/rfl/bson/Writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <string>
#include <string_view>
#include <type_traits>
#include <variant>
#include <vector>

#include "../Result.hpp"
Expand All @@ -18,146 +19,162 @@
namespace rfl {
namespace bson {

/// Please refer to https://mongoc.org/libbson/current/api.html
class Writer {
using ParentType = std::variant<bson_t*, bson_array_builder_t*>;

public:
struct YYBSONOutputArray {
YYBSONOutputArray(yybson_mut_val* _val) : val_(_val) {}
yybson_mut_val* val_;
struct BSONOutputArray {
BSONOutputArray(bson_array_builder_t* _val, ParentType _parent)
: parent_(_parent), val_(_val) {}
ParentType parent_;
bson_array_builder_t* val_;
};

struct YYBSONOutputObject {
YYBSONOutputObject(yybson_mut_val* _val) : val_(_val) {}
yybson_mut_val* val_;
struct BSONOutputObject {
BSONOutputObject(bson_t _val, ParentType _parent)
: parent_(_parent), val_(_val) {}
ParentType parent_;
bson_array_builder_t* val_;
};

struct YYBSONOutputVar {
YYBSONOutputVar(yybson_mut_val* _val) : val_(_val) {}

YYBSONOutputVar(YYBSONOutputArray _arr) : val_(_arr.val_) {}

YYBSONOutputVar(YYBSONOutputObject _obj) : val_(_obj.val_) {}

yybson_mut_val* val_;
};
struct BSONOutputVar {};

using OutputArrayType = YYBSONOutputArray;
using OutputObjectType = YYBSONOutputObject;
using OutputVarType = YYBSONOutputVar;
using OutputArrayType = BSONOutputArray;
using OutputObjectType = BSONOutputObject;
using OutputVarType = BSONOutputVar;

Writer(yybson_mut_doc* _doc) : doc_(_doc) {}
Writer() : { bson_init(&doc_); }

~Writer() = default;

OutputArrayType array_as_root(const size_t _size) const noexcept {
const auto arr = yybson_mut_arr(doc_);
yybson_mut_doc_set_root(doc_, arr);
return OutputArrayType(arr);
}
// TODO
OutputArrayType array_as_root(const size_t _size) const noexcept {}

OutputObjectType object_as_root(const size_t _size) const noexcept {
const auto obj = yybson_mut_obj(doc_);
yybson_mut_doc_set_root(doc_, obj);
return OutputObjectType(obj);
}
// TODO
OutputObjectType object_as_root(const size_t _size) const noexcept {}

OutputVarType null_as_root() const noexcept {
const auto null = yybson_mut_null(doc_);
yybson_mut_doc_set_root(doc_, null);
return OutputVarType(null);
}
// TODO
OutputVarType null_as_root() const noexcept {}

// TODO
template <class T>
OutputVarType value_as_root(const T& _var) const noexcept {
const auto val = from_basic_type(_var);
yybson_mut_doc_set_root(doc_, val.val_);
return OutputVarType(val);
}
OutputVarType value_as_root(const T& _var) const noexcept {}

OutputArrayType add_array_to_array(const size_t _size,
OutputArrayType* _parent) const noexcept {
const auto arr = yybson_mut_arr(doc_);
yybson_mut_arr_add_val(_parent->val_, arr);
return OutputArrayType(arr);
bson_array_builder_t* val;
bson_array_builder_append_array_builder_begin(_parent->val_, &val);
return OutputArrayType(val, _parent->val_);
}

OutputArrayType add_array_to_object(
const std::string& _name, const size_t _size,
OutputObjectType* _parent) const noexcept {
const auto arr = yybson_mut_arr(doc_);
yybson_mut_obj_add(_parent->val_, yybson_mut_strcpy(doc_, _name.c_str()),
arr);
return OutputArrayType(arr);
bson_array_builder_t* val;
bson_append_array_builder_begin(_parent->val_, _name.c_str(),
static_cast<int>(_name.size()), &val);
return OutputArrayType(val, _parent->val_);
}

OutputObjectType add_object_to_array(
const size_t _size, OutputArrayType* _parent) const noexcept {
const auto obj = yybson_mut_obj(doc_);
yybson_mut_arr_add_val(_parent->val_, obj);
return OutputObjectType(obj);
bson_t val;
bson_array_builder_append_document_begin(_parent->val_, &val);
return OutputObjectType(val, _parent->val_);
}

OutputObjectType add_object_to_object(
const std::string& _name, const size_t _size,
OutputObjectType* _parent) const noexcept {
const auto obj = yybson_mut_obj(doc_);
yybson_mut_obj_add(_parent->val_, yybson_mut_strcpy(doc_, _name.c_str()),
obj);
return OutputObjectType(obj);
bson_t val;
bson_append_document_begin(_parent->val_, _name.c_str(),
static_cast<int>(_name.size()), &val);
return OutputObjectType(val, _parent->val_);
}

template <class T>
OutputVarType add_value_to_array(const T& _var,
OutputArrayType* _parent) const noexcept {
const auto val = from_basic_type(_var);
yybson_mut_arr_add_val(_parent->val_, val.val_);
return OutputVarType(val);
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
bson_array_builder_append_utf8(_parent->val_, _val.c_str(),
static_cast<int>(_var.size()));
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
bson_array_builder_append_bool(_parent->val_, _var);
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
bson_array_builder_append_double(_parent->val_,
static_cast<double>(_var));
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
bson_array_builder_append_int64(_parent->val_,
static_cast<std::int32_t>(_var));
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
return OutputVarType{};
}

template <class T>
OutputVarType add_value_to_object(const std::string& _name, const T& _var,
OutputObjectType* _parent) const noexcept {
const auto val = from_basic_type(_var);
yybson_mut_obj_add(_parent->val_, yybson_mut_strcpy(doc_, _name.c_str()),
val.val_);
return OutputVarType(val);
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
bson_append_utf8(_parent->val_, _name.c_str(),
static_cast<int>(_name.c_str()), _val.c_str(),
static_cast<int>(_var.size()));
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
bson_append_bool(_parent->val_, _name.c_str(),
static_cast<int>(_name.c_str()), _var);
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
bson_append_double(_parent->val_, _name.c_str(),
static_cast<int>(_name.c_str()),
static_cast<double>(_var));
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
bson_append_int64(_parent->val_, _name.c_str(),
static_cast<int>(_name.c_str()),
static_cast<std::int32_t>(_var));
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
return OutputVarType{};
}

OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept {
const auto null = yybson_mut_null(doc_);
yybson_mut_arr_add_val(_parent->val_, null);
return OutputVarType(null);
bson_array_builder_append_null(_parent->val_);
return OutputVarType{};
}

OutputVarType add_null_to_object(const std::string& _name,
OutputObjectType* _parent) const noexcept {
const auto null = yybson_mut_null(doc_);
yybson_mut_obj_add(_parent->val_, yybson_mut_strcpy(doc_, _name.c_str()),
null);
return OutputVarType(null);
bson_array_builder_append_null(_parent->val_, _name.c_str(),
static_cast<int>(_name.c_str()));
return OutputVarType{};
}

void end_array(OutputArrayType* _arr) const noexcept {}

void end_object(OutputObjectType* _obj) const noexcept {}
void end_array(OutputArrayType* _arr) const noexcept {
const auto handle = [&](const auto _parent) {
using Type = std::remove_cvref_t<decltype(_parent)>;
if constexpr (std::is_same<Type, bson_array_builder_t*>()) {
bson_array_builder_append_array_builder_end(_parent, _arr->val_);
} else {
bson_append_array_end(_parent, _arr->val_);
}
};
std::visit(handle, _arr->parent_);
}

private:
template <class T>
OutputVarType from_basic_type(const T& _var) const noexcept {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
return OutputVarType(yybson_mut_strcpy(doc_, _var.c_str()));
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
return OutputVarType(yybson_mut_bool(doc_, _var));
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>()) {
return OutputVarType(yybson_mut_real(doc_, static_cast<double>(_var)));
} else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
return OutputVarType(yybson_mut_int(doc_, static_cast<int>(_var)));
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
}
void end_object(OutputObjectType* _obj) const noexcept {
const auto handle = [&](const auto _parent) {
using Type = std::remove_cvref_t<decltype(_parent)>;
if constexpr (std::is_same<Type, bson_array_builder_t*>()) {
bson_array_builder_append_document_end(_parent, _arr->val_);
} else {
bson_append_document_end(_parent, _arr->val_);
}
};
std::visit(handle, _arr->parent_);
}

public:
bson_t b;
bson_t doc_;
};

} // namespace bson
Expand Down

0 comments on commit ee3981d

Please sign in to comment.