Template-heavy implementation of concise binary object representation as described in RFC 7049. Mainly because the cbor serialization from Nlohmann's json library was not fast enough for my use case. If any type cannot be serialized or deserialized this results in a compile error.
Quick example:
using Data = std::vector<std::uint8_t>;
// Minimal standard serialization use case:
std::vector<int> input {1, 50, -10};
Data cbor_repr;
cbor::result result = cbor::to_cbor(input, cbor_repr);
// Result is implicitly convertible into std::size_t, explicitly into bool.
// Bool holds whether serialization was successful.
// The length specifies how many bytes were used for the cbor representation.
if (result)
{
std::size_t length = result;
std::cout << "Length: " << length << std::endl;
}
// Minimal standard deserialization use case:
std::vector<int> parsed;
cbor::result parse_result = cbor::from_cbor(parsed, cbor_repr);
// By default, this statement may throw if the types encountered in the data
// don't match the types you are parsing into.There are more examples in the example.cpp file. The library can be used without exceptions by
setting the CBOR_USE_EXCEPTIONS define to 0. It can also be used without the standard library's containers by
not including stl.h, this still requires the standard library headers for the template handling.
Supported types plain old data types:
boolstd::uint8_t: Serializes into a cbor tiny integer if value allows.std::uint16_t: Serializes into 8 bit integer if value allows.std::uint32_t: Serializes into 16 bit integer if value allows.std::uint64_t: Serializes into 32 bit integer if value allows.std::int8_t: Serializes into a cbor tiny integer if value allows.std::int16_t: Serializes into 8 bit integer if value allows.std::int32_t: Serializes into 16 bit integer if value allows.std::int64_t: Serializes into 32 bit integer if value allows.const char*: Serializes into a cbor text string (utf-8).nullptr_t: Serializes into cbornullvalue.float: Will be serialized into short float if exact. Can be read into a double.double: Will be serialized into single precision float if exact, or short precision float if exact. Cannot be read into a float as precision is never degraded during (de)serialization.d[N]: Any C style array is serialized as a cbor array ofNlong, deserialization requires fixed length array.
Supported STL containers:
std::vector: Serialized into fixed length cbor array, deserialization of indefinite array supported.std::map: Serialized into fixed length cbor map, deserialization of indefinite map supported.std::pair: Serialized into cbor array of two long, deserialization requires fixed length array.std::tuple: Serialized into cbor array equal to the tuple length, deserialization requires fixed length array.std::array: Handled asd[N].std::string: Handled asconst char*. Deserialization supports 'indefinite' strings.
Supported STL smart pointers:
std::shared_ptr: Serializes the dereferenced pointer. If anullptrthis serializes as cbornulltype.std::unique_ptr: Serializes the dereferenced pointer. If anullptrthis serializes as cbornulltype.
Supported CBOR types:
map, indefinite length supported forstd::map.array, indefinite length supported forstd::vector.signed integerunsigned integerdoubleandfloat,short floatare supported. Float precision is never degraded during (de)serialization.booleannulltextandbyteboth treated as strings.
Supported custom type:
cbor_object, this object acts as a read adapter and stores data internally into astd::vector<std::uint8_t>. Any input can be deserialized into this type, after which all methods from theread_adapter_helpercan be used to introspect the data. Additionally it has aprettyPrint()method that produces a human readable string.
This library has been tested using libFuzzer. When fuzzing we cannot rely on the nice compile time properties of the
templates, instead deserialization was performed into a cbor_object. Since the fuzzer liked finding stack overflows
by opening nested indefinite length arrays it is possible to limit the maximum recursion depth. This is done in the
fuzzer binary, if the parser has to deal with malicious data limiting this may be a good idea.
mkdir build
cd build
CC=clang-8 CXX=clang++-8 cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ../cbor/ && make fuzz_corpus_init fuzz_start