Skip to content

Commit

Permalink
Added the first test for BSON
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzicheng1987 committed Jan 16, 2024
1 parent 9594cbe commit 661dced
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 50 deletions.
12 changes: 12 additions & 0 deletions include/rfl/bson.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef RFL_BSON_HPP_
#define RFL_BSON_HPP_

#include "bson/Parser.hpp"
#include "bson/Reader.hpp"
#include "bson/Writer.hpp"
#include "bson/load.hpp"
#include "bson/read.hpp"
#include "bson/save.hpp"
#include "bson/write.hpp"

#endif
17 changes: 10 additions & 7 deletions include/rfl/bson/Reader.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#ifndef RFL_JSON_READER_HPP_
#define RFL_JSON_READER_HPP_
#ifndef RFL_BSON_READER_HPP_
#define RFL_BSON_READER_HPP_

#include <bson/bson.h>

#include <array>
#include <concepts>
Expand Down Expand Up @@ -65,7 +67,8 @@ struct Reader {
if (bson_iter_type(&_var.iter_) != BSON_TYPE_UTF8) {
return rfl::Error("Could not cast to string.");
}
return std::string(bson_iter_utf8(&_var.iter_));
uint32_t length = 0;
return std::string(bson_iter_utf8(&_var.iter_, &length));
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
const auto btype = bson_iter_type(&_var.iter_);
if (btype != BSON_TYPE_BOOL && btype != BSON_TYPE_DOUBLE &&
Expand Down Expand Up @@ -93,8 +96,8 @@ struct Reader {

rfl::Result<InputArrayType> to_array(
const InputVarType& _var) const noexcept {
auto iter = _obj.iter_;
if (bson_iter_type(iter) != BSON_TYPE_ARRAY) {
auto iter = _var.iter_;
if (bson_iter_type(&iter) != BSON_TYPE_ARRAY) {
return Error("Could not cast to an array.");
}
InputArrayType arr;
Expand Down Expand Up @@ -139,10 +142,10 @@ struct Reader {
}

std::vector<InputVarType> to_vec(const InputArrayType& _arr) const noexcept {
auto iter = _obj.iter_;
auto iter = _arr.iter_;
std::vector<InputVarType> vec;
while (bson_iter_next(&iter)) {
vec.push_back(iter);
vec.push_back(InputVarType{iter});
}
return vec;
}
Expand Down
72 changes: 40 additions & 32 deletions include/rfl/bson/Writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@ namespace bson {

/// Please refer to https://mongoc.org/libbson/current/api.html
class Writer {
struct IsArray {
bson_array_builder_t* ptr_;
};

struct IsObject {
bson_t* ptr_;
};

struct IsRoot {};

using ParentType = std::variant<bson_t*, bson_array_builder_t*, IsRoot>;
using ParentType = std::variant<IsArray, IsObject, IsRoot>;

public:
struct BSONOutputArray {
Expand All @@ -38,7 +46,7 @@ class Writer {
BSONOutputObject(bson_t _val, ParentType _parent)
: parent_(_parent), val_(_val) {}
ParentType parent_;
bson_array_builder_t* val_;
bson_t val_;
};

struct BSONOutputVar {};
Expand All @@ -47,13 +55,13 @@ class Writer {
using OutputObjectType = BSONOutputObject;
using OutputVarType = BSONOutputVar;

Writer(const Ref<bson_t>& _doc) : doc_(_doc) {}
Writer(bson_t* _doc) : doc_(_doc) {}

~Writer() = default;

OutputArrayType array_as_root(const size_t _size) const noexcept {
bson_array_builder_t* val = bson_array_builder_new();
return OutputObjectType(val, IsRoot{});
return OutputArrayType(val, IsRoot{});
}

OutputObjectType object_as_root(const size_t _size) const noexcept {
Expand All @@ -78,39 +86,39 @@ class Writer {
OutputArrayType* _parent) const noexcept {
bson_array_builder_t* val;
bson_array_builder_append_array_builder_begin(_parent->val_, &val);
return OutputArrayType(val, _parent->val_);
return OutputArrayType(val, IsArray{_parent->val_});
}

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

OutputObjectType add_object_to_array(
const size_t _size, OutputArrayType* _parent) const noexcept {
bson_t val;
bson_array_builder_append_document_begin(_parent->val_, &val);
return OutputObjectType(val, _parent->val_);
return OutputObjectType(val, IsArray{_parent->val_});
}

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

template <class T>
OutputVarType add_value_to_array(const T& _var,
OutputArrayType* _parent) const noexcept {
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
bson_array_builder_append_utf8(_parent->val_, _val.c_str(),
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>, bool>()) {
bson_array_builder_append_bool(_parent->val_, _var);
Expand All @@ -130,19 +138,19 @@ class Writer {
OutputVarType add_value_to_object(const std::string& _name, const T& _var,
OutputObjectType* _parent) const noexcept {
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(),
bson_append_utf8(&(_parent->val_), _name.c_str(),
static_cast<int>(_name.size()), _var.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);
bson_append_bool(&(_parent->val_), _name.c_str(),
static_cast<int>(_name.size()), _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()),
bson_append_double(&(_parent->val_), _name.c_str(),
static_cast<int>(_name.size()),
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()),
bson_append_int64(&(_parent->val_), _name.c_str(),
static_cast<int>(_name.size()),
static_cast<std::int32_t>(_var));
} else {
static_assert(rfl::always_false_v<T>, "Unsupported type.");
Expand All @@ -157,20 +165,20 @@ class Writer {

OutputVarType add_null_to_object(const std::string& _name,
OutputObjectType* _parent) const noexcept {
bson_array_builder_append_null(_parent->val_, _name.c_str(),
static_cast<int>(_name.c_str()));
bson_append_null(&(_parent->val_), _name.c_str(),
static_cast<int>(_name.size()));
return OutputVarType{};
}

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 if constexpr (std::is_same<Tupe, bson_t>()) {
bson_append_array_end(_parent, _arr->val_);
if constexpr (std::is_same<Type, IsArray>()) {
bson_array_builder_append_array_builder_end(_parent.ptr_, _arr->val_);
} else if constexpr (std::is_same<Type, IsObject>()) {
bson_append_array_builder_end(_parent.ptr_, _arr->val_);
} else if constexpr (std::is_same<Type, IsRoot>()) {
bson_array_builder_build(_arr->val_, doc_.get());
bson_array_builder_build(_arr->val_, doc_);
} else {
static_assert(rfl::always_false_v<Type>, "Unsupported type.");
}
Expand All @@ -181,21 +189,21 @@ class Writer {
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 if constexpr (std::is_same<Tupe, bson_t>()) {
bson_append_document_end(_parent, _arr->val_);
if constexpr (std::is_same<Type, IsArray>()) {
bson_array_builder_append_document_end(_parent.ptr_, &(_obj->val_));
} else if constexpr (std::is_same<Type, IsObject>()) {
bson_append_document_end(_parent.ptr_, &(_obj->val_));
} else if constexpr (std::is_same<Type, IsRoot>()) {
*doc_ = _obj->val_;
} else {
static_assert(rfl::always_false_v<Type>, "Unsupported type.");
}
};
std::visit(handle, _arr->parent_);
std::visit(handle, _obj->parent_);
}

private:
Ref<bson_t> doc_;
bson_t* const doc_;
};

} // namespace bson
Expand Down
17 changes: 11 additions & 6 deletions include/rfl/bson/read.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef RFL_BSON_READ_HPP_
#define RFL_BSON_READ_HPP_

#include <bson/bson.h>

#include <istream>
#include <string>

Expand All @@ -23,22 +25,25 @@ auto read(const InputVarType& _obj) {

/// Parses an object from flexbuf using reflection.
template <class T>
auto read(const char* _bytes, const size_t _size) {
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
const size_t _size) {
bson_t* b = nullptr;
InputVarType doc;
const bool success = bson_init_static(
&doc.iter_, reinterpret_cast<const uint8_t*>(_bytes.data()),
bytes.size());
const bool success =
bson_init_static(b, reinterpret_cast<const uint8_t*>(_bytes), _size);
if (!success) {
return Error("Bytestring was not a valid BSON string.");
}
bson_iter_init(&doc.iter_, b);
const auto result = read<T>(doc);
bson_destroy(&doc.iter_);
bson_destroy(b);
return result;
}

/// Parses an object from BSON using reflection.
template <class T>
Result<internal::wrap_in_rfl_array_t<T>> read(const std::vector<char>& _bytes) {
auto read(const std::vector<char>& _bytes) {
return read<T>(_bytes.data(), _bytes.size());
}

/// Parses an object from a stream.
Expand Down
35 changes: 32 additions & 3 deletions include/rfl/bson/write.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef RFL_BSON_WRITE_HPP_
#define RFL_BSON_WRITE_HPP_

#include <bson/bson.h>

#include <ostream>
#include <sstream>
#include <string>
Expand All @@ -11,13 +13,40 @@
namespace rfl {
namespace bson {

/// Returns a BSON string.
/// Returns BSON bytes.
template <class T>
std::vector<char> write(const T& _obj) {}
std::vector<char> write(const T& _obj) {
using ParentType = parsing::Parent<Writer>;
bson_t* doc;
uint8_t* buf = nullptr;
size_t buflen = 0;

bson_writer_t* bson_writer =
bson_writer_new(&buf, &buflen, 0, bson_realloc_ctx, NULL);

bson_writer_begin(bson_writer, &doc);

const auto rfl_writer = Writer(doc);

Parser<T>::write(rfl_writer, _obj, typename ParentType::Root{});

bson_writer_end(bson_writer);

const auto result = std::vector<char>(reinterpret_cast<char*>(buf),
reinterpret_cast<char*>(buf) + buflen);

bson_free(buf);

bson_writer_destroy(bson_writer);

return result;
}

/// Writes a BSON into an ostream.
template <class T>
std::ostream& write(const T& _obj, std::ostream& _stream) {}
std::ostream& write(const T& _obj, std::ostream& _stream) {
// TODO
}

} // namespace bson
} // namespace rfl
Expand Down
4 changes: 2 additions & 2 deletions include/rfl/flexbuf.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef FLEXBUF_FLEXBUF_HPP_
#define FLEXBUF_FLEXBUF_HPP_
#ifndef RFL_FLEXBUF_HPP_
#define RFL_FLEXBUF_HPP_

#include "flexbuf/Parser.hpp"
#include "flexbuf/Reader.hpp"
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ endif()

add_subdirectory(json)

if (REFLECTCPP_BSON)
add_subdirectory(bson)
endif()

if (REFLECTCPP_FLEXBUFFERS)
add_subdirectory(flexbuffers)
endif()
Expand Down
7 changes: 7 additions & 0 deletions tests/bson/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project(reflect-cpp-bson-tests)

file(GLOB_RECURSE SOURCES "*.cpp")

add_executable(reflect-cpp-bson-tests ${SOURCES})

target_link_libraries(reflect-cpp-bson-tests PRIVATE reflectcpp)
Loading

0 comments on commit 661dced

Please sign in to comment.