diff --git a/README.md b/README.md index 78633b9b..cbc93407 100644 --- a/README.md +++ b/README.md @@ -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 | | diff --git a/docs/README.md b/docs/README.md index 96a40c68..59b524a1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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 diff --git a/docs/bson.md b/docs/bson.md new file mode 100644 index 00000000..bd20bd36 --- /dev/null +++ b/docs/bson.md @@ -0,0 +1,100 @@ +# BSON + +For BSON support, you must also include the header `` 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 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 result = rfl::bson::read(bytes); +``` + +## Loading and saving + +You can also load and save to disc using a very similar syntax: + +```cpp +const rfl::Result result = rfl::bson::load("/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 result = rfl::bson::read(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 from_bson(const InputVarType& _obj); +}; +``` + +And in your source file, you implement `from_bson` as follows: + +```cpp +rfl::Result Person::from_bson(const InputVarType& _obj) { + const auto from_nt = [](auto&& _nt) { + return rfl::from_named_tuple(std::move(_nt)); + }; + return rfl::bson::read>(_obj) + .transform(from_nt); +} +``` + +This will force the compiler to only compile the BSON parsing when the source file is compiled.