Skip to content

Commit

Permalink
Added BSON support; #22
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzicheng1987 committed Jan 19, 2024
1 parent 151e606 commit 5a34c9b
Show file tree
Hide file tree
Showing 82 changed files with 2,267 additions and 14 deletions.
18 changes: 12 additions & 6 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ jobs:
linux-gcc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
submodules: recursive
fetch-depth: 0
- name: Run vcpkg
uses: lukka/run-vcpkg@v11
- name: install dependencies
Expand All @@ -18,8 +20,9 @@ jobs:
- name: Run test
run: |
g++ --version
cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_BSON=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build -j 4
./build/tests/bson/reflect-cpp-bson-tests
./build/tests/flexbuffers/reflect-cpp-flexbuffers-tests
./build/tests/json/reflect-cpp-json-tests
./build/tests/xml/reflect-cpp-xml-tests
Expand All @@ -28,9 +31,11 @@ jobs:
linux-clang:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
submodules: recursive
fetch-depth: 0
- name: Run vcpkg
uses: lukka/run-vcpkg@v11
- uses: KyleMayes/install-llvm-action@v1
Expand All @@ -47,8 +52,9 @@ jobs:
CXX: clang++
run: |
clang --version
cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_BSON=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build -j 4
./build/tests/bson/reflect-cpp-bson-tests
./build/tests/flexbuffers/reflect-cpp-flexbuffers-tests
./build/tests/json/reflect-cpp-json-tests
./build/tests/xml/reflect-cpp-xml-tests
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
**/build_clang/**

# Output files
*.bson
*.json
*.fb
*.xml
Expand Down
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
cmake_minimum_required(VERSION 3.15)

option(REFLECTCPP_BUILD_SHARED "Build shared library" OFF)
option(REFLECTCPP_BSON "Enable BSON support" OFF)
option(REFLECTCPP_FLEXBUFFERS "Enable flexbuffers support" OFF)
option(REFLECTCPP_XML "Enable XML support" OFF)
option(REFLECTCPP_YAML "Enable YAML support" OFF)

option(REFLECTCPP_BUILD_TESTS "Build tests" OFF)

# enable vcpkg if require features other than JSON
if (REFLECTCPP_FLEXBUFFERS OR REFLECTCPP_XML OR REFLECTCPP_YAML)
if (REFLECTCPP_BSON OR REFLECTCPP_FLEXBUFFERS OR REFLECTCPP_XML OR REFLECTCPP_YAML)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "Vcpkg toolchain file")
endif ()

Expand All @@ -24,6 +25,11 @@ endif ()

target_include_directories(reflectcpp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

if (REFLECTCPP_BSON)
find_package(bson-1.0 CONFIG REQUIRED)
target_link_libraries(reflectcpp PRIVATE $<IF:$<TARGET_EXISTS:mongo::bson_static>,mongo::bson_static,mongo::bson_shared>)
endif ()

if (REFLECTCPP_FLEXBUFFERS)
find_package(flatbuffers CONFIG REQUIRED)
target_link_libraries(reflectcpp INTERFACE flatbuffers::flatbuffers)
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ The following table lists the serialization formats currently supported by refle

| Format | Library | Version | License | Remarks |
|--------------|------------------------------------------------------|--------------|------------| -----------------------------------------------------|
| JSON | [YYJSON](https://github.com/ibireme/yyjson) | >= 0.8.0 | MIT | out-of-the-box support, included in this repository |
| JSON | [yyjson](https://github.com/ibireme/yyjson) | >= 0.8.0 | MIT | out-of-the-box support, included in this repository |
| BSON | [libbson](https://github.com/mongodb/libbson) | >= 1.25.1 | Apache 2.0 | |
| flexbuffers | [flatbuffers](https://github.com/google/flatbuffers) | >= 23.5.26 | Apache 2.0 | |
| XML | [pugixml](https://github.com/zeux/pugixml) | >= 1.14 | MIT | |
| YAML | [yaml-cpp](https://github.com/jbeder/yaml-cpp) | >= 0.8.0 | MIT | |
Expand Down Expand Up @@ -448,6 +449,7 @@ To use reflect-cpp in your project:
```cmake
add_subdirectory(reflect-cpp) # Add this project as a subdirectory
set(REFLECTCPP_BSON ON) # Optional
set(REFLECTCPP_FLEXBUFFERS ON) # Optional
set(REFLECTCPP_XML ON) # Optional
set(REFLECTCPP_YAML ON) # Optional
Expand Down Expand Up @@ -494,7 +496,7 @@ git submodule update --init
./vcpkg/bootstrap-vcpkg.bat # Windows
# You may be prompted to install additional dependencies.

cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_BSON=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build -j 4 # gcc, clang
cmake --build build --config Release -j 4 # MSVC
```
Expand Down
8 changes: 5 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@

5.1) [JSON](https://github.com/getml/reflect-cpp/blob/main/docs/json.md)

5.2) [flexbuffers](https://github.com/getml/reflect-cpp/blob/main/docs/flexbuffers.md)
5.2) [BSON](https://github.com/getml/reflect-cpp/blob/main/docs/bson.md)

5.3) [XML](https://github.com/getml/reflect-cpp/blob/main/docs/xml.md)
5.3) [flexbuffers](https://github.com/getml/reflect-cpp/blob/main/docs/flexbuffers.md)

5.4) [YAML](https://github.com/getml/reflect-cpp/blob/main/docs/yaml.md)
5.4) [XML](https://github.com/getml/reflect-cpp/blob/main/docs/xml.md)

5.5) [YAML](https://github.com/getml/reflect-cpp/blob/main/docs/yaml.md)

## 6) Advanced topics

Expand Down
100 changes: 100 additions & 0 deletions docs/bson.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# BSON

For BSON support, you must also include the header `<rfl/bson.hpp>` and link to the libbson library (https://github.com/mongodb/libbson).

Like the name implies, BSON is a JSON-like binary format. It is most notably used by MongoDB.

## Reading and writing

Suppose you have a struct like this:

```cpp
struct Person {
std::string first_name;
std::string last_name;
rfl::Timestamp<"%Y-%m-%d"> birthday;
std::vector<Person> children;
};
```
A `person` can be turned into a bytes vector like this:
```cpp
const auto person = Person{...};
const auto bytes = rfl::bson::write(person);
```

You can parse bytes like this:

```cpp
const rfl::Result<Person> result = rfl::bson::read<Person>(bytes);
```

## Loading and saving

You can also load and save to disc using a very similar syntax:

```cpp
const rfl::Result<Person> result = rfl::bson::load<Person>("/path/to/file.bson");

const auto person = Person{...};
rfl::bson::save("/path/to/file.bson", person);
```
## Reading from and writing into streams
You can also read from and write into any `std::istream` and `std::ostream` respectively.
```cpp
const rfl::Result<Person> result = rfl::bson::read<Person>(my_istream);
const auto person = Person{...};
rfl::bson::write(person, my_ostream);
```

Note that `std::cout` is also an ostream, so this works as well:

```cpp
rfl::bson::write(person, std::cout) << std::endl;
```
(Since BSON is a binary format, the readability of this will be limited, but it might be useful for debugging).
## Custom constructors
One of the great things about C++ is that it gives you control over
when and how you code is compiled.
For large and complex systems of structs, it is often a good idea to split up
your code into smaller compilation units. You can do so using custom constructors.
For the BSON format, these must be a static function on your struct or class called
`from_bson` that take a `rfl::bson::Reader::InputVarType` as input and return
the class or the class wrapped in `rfl::Result`.
In your header file you can write something like this:
```cpp
struct Person {
rfl::Rename<"firstName", std::string> first_name;
rfl::Rename<"lastName", std::string> last_name;
rfl::Timestamp<"%Y-%m-%d"> birthday;
using InputVarType = typename rfl::bson::Reader::InputVarType;
static rfl::Result<Person> from_bson(const InputVarType& _obj);
};
```

And in your source file, you implement `from_bson` as follows:

```cpp
rfl::Result<Person> Person::from_bson(const InputVarType& _obj) {
const auto from_nt = [](auto&& _nt) {
return rfl::from_named_tuple<Person>(std::move(_nt));
};
return rfl::bson::read<rfl::named_tuple_t<Person>>(_obj)
.transform(from_nt);
}
```
This will force the compiler to only compile the BSON parsing when the source file is compiled.
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: 17 additions & 0 deletions include/rfl/bson/Parser.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef RFL_BSON_PARSER_HPP_
#define RFL_BSON_PARSER_HPP_

#include "../parsing/Parser.hpp"
#include "Reader.hpp"
#include "Writer.hpp"

namespace rfl {
namespace bson {

template <class T>
using Parser = parsing::Parser<Reader, Writer, T>;

}
} // namespace rfl

#endif
Loading

0 comments on commit 5a34c9b

Please sign in to comment.