Skip to content

Commit

Permalink
Added documentation for CBOR
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzicheng1987 committed Jan 24, 2024
1 parent b2c5487 commit f9a25ba
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 10 deletions.
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ 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 |
| BSON | [libbson](https://github.com/mongodb/libbson) | >= 1.25.1 | Apache 2.0 | |
| CBOR | [tinycbor](https://github.com/intel/tinycbor) | >= 0.6.0 | MIT | |
| 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 | |
| BSON | [libbson](https://github.com/mongodb/libbson) | >= 1.25.1 | Apache 2.0 | JSON-like binary format |
| CBOR | [tinycbor](https://github.com/intel/tinycbor) | >= 0.6.0 | MIT | JSON-like binary format |
| flexbuffers | [flatbuffers](https://github.com/google/flatbuffers) | >= 23.5.26 | Apache 2.0 | Schema-less version of flatbuffers, binary format |
| XML | [pugixml](https://github.com/zeux/pugixml) | >= 1.14 | MIT | Textual format used in many legacy projects |
| YAML | [yaml-cpp](https://github.com/jbeder/yaml-cpp) | >= 0.8.0 | MIT | Textual format with an emphasis on readability |

Support for more serialization formats is in development. Refer to the [issues](https://github.com/getml/reflect-cpp/issues) for details.

Expand Down Expand Up @@ -70,8 +70,7 @@ The resulting JSON string looks like this:
{"first_name":"Homer","last_name":"Simpson","age":45}
```

Or you can use another format, such as YAML. This will work for just about
any example in the entire documentation or any supported format.
Or you can use another format, such as YAML.

```cpp
#include <rfl/yaml.hpp>
Expand All @@ -90,6 +89,21 @@ last_name: Simpson
age: 45
```
This will work for just about any example in the entire documentation
and any supported format:
```cpp
rfl::bson::write(homer);
rfl::cbor::write(homer);
rfl::flexbuf::write(homer);
rfl::xml::write(homer);

rfl::bson::read<Person>(bson_bytes);
rfl::cbor::read<Person>(cbor_bytes);
rfl::flexbuf::read<Person>(flexbuf_bytes);
rfl::xml::read<Person>(xml_string);
```

## More Comprehensive Example

```cpp
Expand Down
8 changes: 5 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,13 @@

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

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

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

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

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

## 6) Advanced topics

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

For CBOR support, you must also include the header `<rfl/cbor.hpp>` and link to the tinycbor library (https://github.com/intel/tinycbor).

CBOR or Concise Binary Object Representation, is a JSON-like binary format with an emphasis on small binary sizes.

## 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 std::vector<char> bytes = rfl::cbor::write(person);
```

You can parse bytes like this:

```cpp
const rfl::Result<Person> result = rfl::cbor::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::cbor::load<Person>("/path/to/file.cbor");

const auto person = Person{...};
rfl::cbor::save("/path/to/file.cbor", 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::cbor::read<Person>(my_istream);
const auto person = Person{...};
rfl::cbor::write(person, my_ostream);
```

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

```cpp
rfl::cbor::write(person, std::cout) << std::endl;
```
(Since CBOR 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 CBOR format, these must be a static function on your struct or class called
`from_cbor` that take a `rfl::cbor::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::cbor::Reader::InputVarType;
static rfl::Result<Person> from_cbor(const InputVarType& _obj);
};
```

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

```cpp
rfl::Result<Person> Person::from_cbor(const InputVarType& _obj) {
const auto from_nt = [](auto&& _nt) {
return rfl::from_named_tuple<Person>(std::move(_nt));
};
return rfl::cbor::read<rfl::named_tuple_t<Person>>(_obj)
.transform(from_nt);
}
```
This will force the compiler to only compile the CBOR parsing when the source file is compiled.

0 comments on commit f9a25ba

Please sign in to comment.