-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5a34c9b
commit f2d9779
Showing
86 changed files
with
2,334 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,7 @@ | |
|
||
# Output files | ||
*.bson | ||
*.cbor | ||
*.json | ||
*.fb | ||
*.xml | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#ifndef RFL_CBOR_HPP_ | ||
#define RFL_CBOR_HPP_ | ||
|
||
#include "cbor/Parser.hpp" | ||
#include "cbor/Reader.hpp" | ||
#include "cbor/Writer.hpp" | ||
#include "cbor/load.hpp" | ||
#include "cbor/read.hpp" | ||
#include "cbor/save.hpp" | ||
#include "cbor/write.hpp" | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef RFL_CBOR_PARSER_HPP_ | ||
#define RFL_CBOR_PARSER_HPP_ | ||
|
||
#include "../parsing/Parser.hpp" | ||
#include "Reader.hpp" | ||
#include "Writer.hpp" | ||
|
||
namespace rfl { | ||
namespace parsing { | ||
|
||
/// CBOR requires us to explicitly set the number of fields in advance. Because | ||
This comment has been minimized.
Sorry, something went wrong. |
||
/// of that, we require all of the fields and then set them to nullptr, if | ||
/// necessary. | ||
template <class... FieldTypes> | ||
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, | ||
NamedTuple<FieldTypes...>> | ||
struct Parser<cbor::Reader, cbor::Writer, NamedTuple<FieldTypes...>> | ||
: public NamedTupleParser<cbor::Reader, cbor::Writer, | ||
/*_ignore_empty_containers=*/false, | ||
/*_all_required=*/true, FieldTypes...> { | ||
}; | ||
|
||
template <class... Ts> | ||
requires AreReaderAndWriter<cbor::Reader, cbor::Writer, std::tuple<Ts...>> | ||
struct Parser<cbor::Reader, cbor::Writer, std::tuple<Ts...>> | ||
: public TupleParser<cbor::Reader, cbor::Writer, | ||
/*_ignore_empty_containers=*/false, | ||
/*_all_required=*/true, Ts...> { | ||
}; | ||
|
||
} // namespace parsing | ||
} // namespace rfl | ||
|
||
namespace rfl { | ||
namespace cbor { | ||
|
||
template <class T> | ||
using Parser = parsing::Parser<Reader, Writer, T>; | ||
|
||
} | ||
} // namespace rfl | ||
|
||
#endif |
Oops, something went wrong.
@liuzicheng1987 What is meant by this comment? CBOR certainly specifies indefinite-length maps, and
jsoncons
seems to support them as well. Maybe this was a constraint left over from TinyCBOR, or just the initial level of support?