{"id":20585749,"url":"https://github.com/chronoxor/cppserialization","last_synced_at":"2025-06-19T07:33:25.430Z","repository":{"id":44164736,"uuid":"82973671","full_name":"chronoxor/CppSerialization","owner":"chronoxor","description":"Performance comparison of the most popular C++ serialization protocols such as Cap'n'Proto, FastBinaryEncoding, Flatbuffers, Protobuf, JSON","archived":false,"fork":false,"pushed_at":"2024-03-09T11:54:27.000Z","size":5344,"stargazers_count":142,"open_issues_count":2,"forks_count":40,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-12-11T10:37:47.946Z","etag":null,"topics":["capnproto","flatbuffers","json","low-latency","performance","protobuf","serialization"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chronoxor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-02-23T21:35:03.000Z","updated_at":"2024-12-09T01:38:31.000Z","dependencies_parsed_at":"2024-03-09T12:25:09.500Z","dependency_job_id":"3a337227-12bb-40f6-bb8b-e0897f47c633","html_url":"https://github.com/chronoxor/CppSerialization","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FCppSerialization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FCppSerialization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FCppSerialization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FCppSerialization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chronoxor","download_url":"https://codeload.github.com/chronoxor/CppSerialization/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230423559,"owners_count":18223435,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["capnproto","flatbuffers","json","low-latency","performance","protobuf","serialization"],"created_at":"2024-11-16T07:09:15.513Z","updated_at":"2024-12-19T11:10:41.212Z","avatar_url":"https://github.com/chronoxor.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CppSerialization\n\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![Release](https://img.shields.io/github/release/chronoxor/CppSerialization.svg?sort=semver)](https://github.com/chronoxor/CppSerialization/releases)\n\u003cbr/\u003e\n[![Linux (clang)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-linux-clang.yml/badge.svg)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-linux-clang.yml)\n[![Linux (gcc)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-linux-gcc.yml/badge.svg)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-linux-gcc.yml)\n[![MacOS](https://github.com/chronoxor/CppSerialization/actions/workflows/build-macos.yml/badge.svg)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-macos.yml)\n\u003cbr/\u003e\n[![Windows (MSYS2)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-windows-msys2.yml/badge.svg)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-windows-msys2.yml)\n[![Windows (MinGW)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-windows-mingw.yml/badge.svg)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-windows-mingw.yml)\n[![Windows (Visual Studio)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-windows-vs.yml/badge.svg)](https://github.com/chronoxor/CppSerialization/actions/workflows/build-windows-vs.yml)\n\nC++ Serialization Library provides functionality to serialize/deserialize\nobjects using different protocols such as Cap'n'Proto, FastBinaryEncoding,\nFlatbuffers, Protobuf, SimpleBinaryEncoding, JSON.\n\nPerformance comparison based on the [Domain model](#domain-model) with one\naccount, one wallet and three orders total size of 128 bytes:\n\n| Protocol                                                                     | Message size | Serialization time | Deserialization time |\n| :--------------------------------------------------------------------------: | -----------: | -----------------: | -------------------: |\n| [Cap'n'Proto](https://capnproto.org)                                         |    208 bytes |             558 ns |               359 ns |\n| [FastBinaryEncoding](https://github.com/chronoxor/FastBinaryEncoding)        |    234 bytes |              66 ns |                82 ns |\n| [FlatBuffers](https://google.github.io/flatbuffers)                          |    280 bytes |             830 ns |               290 ns |\n| [Protobuf](https://developers.google.com/protocol-buffers)                   |    120 bytes |             628 ns |               759 ns |\n| [SimpleBinaryEncoding](https://github.com/real-logic/simple-binary-encoding) |    138 bytes |              35 ns |                85 ns |\n| [JSON](http://rapidjson.org)                                                 |    301 bytes |             740 ns |               500 ns |\n\n[CppSerialization API reference](https://chronoxor.github.io/CppSerialization/index.html)\n\n# Contents\n  * [Features](#features)\n  * [Requirements](#requirements)\n  * [How to build?](#how-to-build)\n  * [Domain model](#domain-model)\n  * [Cap'n'Proto serialization](#capnproto-serialization)\n    * [Cap'n'Proto schema](#capnproto-schema)\n    * [Cap'n'Proto schema compilation](#capnproto-schema-compilation)\n    * [Cap'n'Proto serialization methods](#capnproto-serialization-methods)\n    * [Cap'n'Proto example](#capnproto-example)\n    * [Cap'n'Proto performance](#capnproto-performance)\n  * [FastBinaryEncoding serialization](#fastbinaryencoding-serialization)\n    * [FastBinaryEncoding schema](#fastbinaryencoding-schema)\n    * [FastBinaryEncoding schema compilation](#fastbinaryencoding-schema-compilation)\n    * [FastBinaryEncoding serialization methods](#fastbinaryencoding-serialization-methods)\n    * [FastBinaryEncoding example](#fastbinaryencoding-example)\n    * [FastBinaryEncoding performance](#fastbinaryencoding-performance)\n  * [FlatBuffers serialization](#flatbuffers-serialization)\n    * [FlatBuffers schema](#flatbuffers-schema)\n    * [FlatBuffers schema compilation](#flatbuffers-schema-compilation)\n    * [FlatBuffers serialization methods](#flatbuffers-serialization-methods)\n    * [FlatBuffers example](#flatbuffers-example)\n    * [FlatBuffers performance](#flatbuffers-performance)\n  * [Protobuf serialization](#protobuf-serialization)\n    * [Protobuf schema](#protobuf-schema)\n    * [Protobuf schema compilation](#protobuf-schema-compilation)\n    * [Protobuf serialization methods](#protobuf-serialization-methods)\n    * [Protobuf example](#protobuf-example)\n    * [Protobuf performance](#protobuf-performance)\n  * [SimpleBinaryEncoding serialization](#simplebinaryencoding-serialization)\n    * [SimpleBinaryEncoding schema](#simplebinaryencoding-schema)\n    * [SimpleBinaryEncoding schema compilation](#simplebinaryencoding-schema-compilation)\n    * [SimpleBinaryEncoding serialization methods](#simplebinaryencoding-serialization-methods)\n    * [SimpleBinaryEncoding example](#simplebinaryencoding-example)\n    * [SimpleBinaryEncoding performance](#simplebinaryencoding-performance)\n  * [JSON serialization](#json-serialization)\n    * [JSON serialization methods](#json-serialization-methods)\n    * [JSON example](#json-example)\n    * [JSON performance](#json-performance)\n\n# Features\n* Cross platform (Linux, MacOS, Windows)\n* Binary serialization using [Cap'n'Proto library](https://capnproto.org)\n* Binary serialization using [FastBinaryEncoding library](https://github.com/chronoxor/FastBinaryEncoding)\n* Binary serialization using [FlatBuffers library](https://google.github.io/flatbuffers)\n* Binary serialization using [Protobuf library](https://developers.google.com/protocol-buffers)\n* Binary serialization using [SimpleBinaryEncoding library](https://github.com/real-logic/simple-binary-encoding)\n* JSON serialization using [RapidJSON library](http://rapidjson.org)\n\n# Requirements\n* Linux\n* MacOS\n* Windows\n* [cmake](https://www.cmake.org)\n* [gcc](https://gcc.gnu.org)\n* [git](https://git-scm.com)\n* [gil](https://github.com/chronoxor/gil.git)\n* [python3](https://www.python.org)\n\nOptional:\n* [clang](https://clang.llvm.org)\n* [CLion](https://www.jetbrains.com/clion)\n* [MSYS2](https://www.msys2.org)\n* [MinGW](https://mingw-w64.org/doku.php)\n* [Visual Studio](https://www.visualstudio.com)\n\n# How to build?\n\n### Linux: install required packages\n```shell\nsudo apt-get install -y binutils-dev uuid-dev\n```\n\n### Install [gil (git links) tool](https://github.com/chronoxor/gil)\n```shell\npip3 install gil\n```\n\n### Setup repository\n```shell\ngit clone https://github.com/chronoxor/CppSerialization.git\ncd CppSerialization\ngil update\n```\n\n### Linux\n```shell\ncd build\n./unix.sh\n```\n\n### MacOS\n```shell\ncd build\n./unix.sh\n```\n\n### Windows (MSYS2)\n```shell\ncd build\nunix.bat\n```\n\n### Windows (MinGW)\n```shell\ncd build\nmingw.bat\n```\n\n### Windows (Visual Studio)\n```shell\ncd build\nvs.bat\n```\n\n# Domain model\nThe first step you should perform to use CppSerialization library is to provide\na domain model (aka business objects). Domain model is a set of structures or\nclasses that related to each other and might be aggregated in some hierarchy.\n\nThere is an example domain model which describes Account-Balance-Orders\nrelation of some abstract trading platform:\n\n```c++\n#include \u003cstring\u003e\n#include \u003cvector\u003e\n\nnamespace TradeProto {\n\nenum class OrderSide : uint8_t\n{\n    BUY,\n    SELL\n};\n\nenum class OrderType : uint8_t\n{\n    MARKET,\n    LIMIT,\n    STOP\n};\n\nstruct Order\n{\n    int Id;\n    char Symbol[10];\n    OrderSide Side;\n    OrderType Type;\n    double Price;\n    double Volume;\n\n    Order() : Order(0, \"\u003c\\?\\?\\?\u003e\", OrderSide::BUY, OrderType::MARKET, 0.0, 0.0) {}\n    Order(int id, const std::string\u0026 symbol, OrderSide side, OrderType type, double price, double volume)\n    {\n        Id = id;\n        std::memcpy(Symbol, symbol.c_str(), std::min(symbol.size() + 1, sizeof(Symbol)));\n        Side = side;\n        Type = type;\n        Price = price;\n        Volume = volume;\n    }\n};\n\nstruct Balance\n{\n    char Currency[10];\n    double Amount;\n\n    Balance() : Balance(\"\u003c\\?\\?\\?\u003e\", 0.0) {}\n    Balance(const std::string\u0026 currency, double amount)\n    {\n        std::memcpy(Currency, currency.c_str(), std::min(currency.size() + 1, sizeof(Currency)));\n        Amount = amount;\n    }\n};\n\nstruct Account\n{\n    int Id;\n    std::string Name;\n    Balance Wallet;\n    std::vector\u003cOrder\u003e Orders;\n\n    Account() : Account(0, \"\u003c\\?\\?\\?\u003e\", \"\u003c\\?\\?\\?\u003e\", 0.0) {}\n    Account(int id, const char* name, const char* currency, double amount) : Wallet(currency, amount)\n    {\n        Id = id;\n        Name = name;\n    }\n};\n\n} // namespace TradeProto\n```\n\nThe next step you should provide serialization methods for the domain model.\n\n# Cap'n'Proto serialization\nCap'n'Proto serialization is based on [Cap'n'Proto library](https://capnproto.org).\n\n## Cap'n'Proto schema\nCap'n'Proto serialization starts with describing a model schema. For our domain\nmodel the schema will be the following:\n\n```proto\n# Unique file ID, generated by 'capnp id'\n@0xd4b6e00623bed170;\n\nusing Cxx = import \"/capnp/c++.capnp\";\n$Cxx.namespace(\"Trade::capnproto\");\n\nenum OrderSide\n{\n    buy @0;\n    sell @1;\n}\n\nenum OrderType\n{\n    market @0;\n    limit @1;\n    stop @2;\n}\n\nstruct Order\n{\n    id @0 : Int32;\n    symbol @1 : Text;\n    side @2 : OrderSide;\n    type @3 : OrderType;\n    price @4 : Float64 = 0.0;\n    volume @5 : Float64 = 0.0;\n}\n\nstruct Balance\n{\n    currency @0 : Text;\n    amount @1 : Float64 = 0.0;\n}\n\nstruct Account\n{\n    id @0 : Int32;\n    name @1 : Text;\n    wallet @2 : Balance;\n    orders @3 : List(Order);\n}\n```\n\n## Cap'n'Proto schema compilation\nThe next step is a schema compilation using 'capnpc' utility which will create\na generated code for required programming language.\n\nThe following command will create a C++ generated code:\n```shell\ncapnp compile -I capnproto/c++/src -oc++ trade.capnp\n```\n\nIt is possible to use capnp_generate_cpp() in CMakeLists.txt to generate code\nusing 'cmake' utility:\n```cmake\ncapnp_generate_cpp(CAPNP_HEADERS CAPNP_SOURCES trade.capnp)\n```\n\nAs the result 'trade.capnp.h' and 'trade.capnp.c++' files will be generated.\n\n## Cap'n'Proto serialization methods\nFinally you should extend your domain model with a Cap'n'Proto serialization\nmethods:\n\n```c++\n#include \"capnp/serialize.h\"\n#include \"capnproto/trade.capnp.h\"\n\n#include \u003calgorithm\u003e\n\nnamespace TradeProto {\n\nstruct Order\n{\n    ...\n\n    // Cap'n'Proto serialization\n\n    void Serialize(Trade::capnproto::Order::Builder\u0026 builder)\n    {\n        builder.setId(Id);\n        builder.setSymbol(Symbol);\n        builder.setSide((Trade::capnproto::OrderSide)Side);\n        builder.setType((Trade::capnproto::OrderType)Type);\n        builder.setPrice(Price);\n        builder.setVolume(Volume);\n    }\n\n    void Deserialize(const Trade::capnproto::Order::Reader\u0026 reader)\n    {\n        Id = reader.getId();\n        std::string symbol = reader.getSymbol();\n        std::memcpy(Symbol, symbol.c_str(), std::min(symbol.size() + 1, sizeof(Symbol)));\n        Side = (OrderSide)reader.getSide();\n        Type = (OrderType)reader.getType();\n        Price = reader.getPrice();\n        Volume = reader.getVolume();\n    }\n\n    ...\n};\n\nstruct Balance\n{\n    ...\n\n    // Cap'n'Proto serialization\n\n    void Serialize(Trade::capnproto::Balance::Builder\u0026 builder)\n    {\n        builder.setCurrency(Currency);\n        builder.setAmount(Amount);\n    }\n\n    void Deserialize(const Trade::capnproto::Balance::Reader\u0026 reader)\n    {\n        std::string currency = reader.getCurrency();\n        std::memcpy(Currency, currency.c_str(), std::min(currency.size() + 1, sizeof(Currency)));\n        Amount = reader.getAmount();\n    }\n\n    ...\n};\n\nstruct Account\n{\n    ...\n\n    // Cap'n'Proto serialization\n\n    void Serialize(Trade::capnproto::Account::Builder\u0026 builder)\n    {\n        builder.setId(Id);\n        builder.setName(Name);\n        auto wallet = builder.initWallet();\n        Wallet.Serialize(wallet);\n        auto orders = builder.initOrders((unsigned)Orders.size());\n        unsigned index = 0;\n        for (auto\u0026 order : Orders)\n        {\n            auto o = orders[index++];\n            order.Serialize(o);\n        }\n    }\n\n    void Deserialize(const Trade::capnproto::Account::Reader\u0026 reader)\n    {\n        Id = reader.getId();\n        Name = reader.getName().cStr();\n        Wallet.Deserialize(reader.getWallet());\n        Orders.clear();\n        for (auto o : reader.getOrders())\n        {\n            Order order;\n            order.Deserialize(o);\n            Orders.emplace_back(order);\n        }\n    }\n\n    ...\n};\n\n} // namespace TradeProto\n```\n\n## Cap'n'Proto example\nHere comes the usage example of FlatBuffers serialize/deserialize functionality:\n\n```c++\n#include \"../proto/trade.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    TradeProto::Account account(1, \"Test\", \"USD\", 1000);\n    account.Orders.emplace_back(TradeProto::Order(1, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::MARKET, 1.23456, 1000));\n    account.Orders.emplace_back(TradeProto::Order(2, \"EURUSD\", TradeProto::OrderSide::SELL, TradeProto::OrderType::LIMIT, 1.0, 100));\n    account.Orders.emplace_back(TradeProto::Order(3, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::STOP, 1.5, 10));\n\n    // Serialize the account to the Cap'n'Proto stream\n    capnp::MallocMessageBuilder output;\n    Trade::capnproto::Account::Builder builder = output.initRoot\u003cTrade::capnproto::Account\u003e();\n    account.Serialize(builder);\n    kj::VectorOutputStream buffer;\n    writeMessage(buffer, output);\n\n    // Show original and Cap'n'Proto serialized sizes\n    std::cout \u003c\u003c \"Original size: \" \u003c\u003c account.size() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Cap'n'Proto size: \" \u003c\u003c buffer.getArray().size() \u003c\u003c std::endl;\n\n    // Deserialize the account from the Cap'n'Proto stream\n    kj::ArrayInputStream array(buffer.getArray());\n    capnp::InputStreamMessageReader input(array);\n    TradeProto::Account deserialized;\n    deserialized.Deserialize(input.getRoot\u003cTrade::capnproto::Account\u003e());\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Id = \" \u003c\u003c deserialized.Id \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Name = \" \u003c\u003c deserialized.Name \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Currency = \" \u003c\u003c deserialized.Wallet.Currency \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Amount = \" \u003c\u003c deserialized.Wallet.Amount \u003c\u003c std::endl;\n    for (auto\u0026 order : deserialized.Orders)\n    {\n        std::cout \u003c\u003c \"Account.Order =\u003e Id: \" \u003c\u003c order.Id\n            \u003c\u003c \", Symbol: \" \u003c\u003c order.Symbol\n            \u003c\u003c \", Side: \" \u003c\u003c (int)order.Side\n            \u003c\u003c \", Type: \" \u003c\u003c (int)order.Type\n            \u003c\u003c \", Price: \" \u003c\u003c order.Price\n            \u003c\u003c \", Volume: \" \u003c\u003c order.Volume\n            \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nOutput of the example is the following:\n```\nOriginal size: 128\nCap'n'Proto size: 208\n\nAccount.Id = 1\nAccount.Name = Test\nAccount.Wallet.Currency = USD\nAccount.Wallet.Amount = 1000\nAccount.Order =\u003e Id: 1, Symbol: EURUSD, Side: 0, Type: 0, Price: 1.23456, Volume: 1000\nAccount.Order =\u003e Id: 2, Symbol: EURUSD, Side: 1, Type: 1, Price: 1, Volume: 100\nAccount.Order =\u003e Id: 3, Symbol: EURUSD, Side: 0, Type: 2, Price: 1.5, Volume: 10\n```\n\n## Cap'n'Proto performance\nCap'n'Proto serialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.431 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:21:25 2018\nUTC timestamp: Wed Jul 18 10:21:25 2018\n===============================================================================\nBenchmark: Cap'n'Proto-Serialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: Cap'n'Proto-Serialize\nAverage time: 558 ns/op\nMinimal time: 558 ns/op\nMaximal time: 568 ns/op\nTotal time: 4.783 s\nTotal operations: 8562741\nTotal bytes: 1.674 GiB\nOperations throughput: 1789911 ops/s\nBytes throughput: 355.055 MiB/s\nCustom values:\n        MessageSize: 208\n        OriginalSize: 128\n===============================================================================\n```\n\nCap'n'Proto deserialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.631 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:22:27 2018\nUTC timestamp: Wed Jul 18 10:22:27 2018\n===============================================================================\nBenchmark: Cap'n'Proto-Deserialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: Cap'n'Proto-Deserialize\nAverage time: 359 ns/op\nMinimal time: 359 ns/op\nMaximal time: 361 ns/op\nTotal time: 4.828 s\nTotal operations: 13440063\nTotal bytes: 2.618 GiB\nOperations throughput: 2783738 ops/s\nBytes throughput: 552.198 MiB/s\nCustom values:\n        MessageSize: 208\n        OriginalSize: 128\n===============================================================================\n```\n\n# FastBinaryEncoding serialization\nFastBinaryEncoding serialization is based on [FastBinaryEncoding library](https://github.com/chronoxor/FastBinaryEncoding).\n\n## FastBinaryEncoding schema\nFastBinaryEncoding serialization starts with describing a model schema. For our\ndomain model the schema will be the following:\n\n```proto\npackage trade\n\nenum OrderSide : byte\n{\n    buy;\n    sell;\n}\n\nenum OrderType : byte\n{\n    market;\n    limit;\n    stop;\n}\n\nstruct Order\n{\n    [key] int32 id;\n    string symbol;\n    OrderSide side;\n    OrderType type;\n    double price = 0.0;\n    double volume = 0.0;\n}\n\nstruct Balance\n{\n    [key] string currency;\n    double amount = 0.0;\n}\n\nstruct Account\n{\n    [key] int32 id;\n    string name;\n    Balance wallet;\n    Order[] orders;\n}\n```\n\n## FastBinaryEncoding schema compilation\nThe next step is a schema compilation using 'fbec' utility which will create\na generated code for required programming language.\n\nThe following command will create a C++ generated code:\n```shell\nfbec --cpp --input=trade.fbe --output=.\n```\n\nIt is possible to use add_custom_command() in CMakeLists.txt to generate code\nusing 'cmake' utility:\n```cmake\nadd_custom_command(TARGET example POST_BUILD COMMAND fbec --cpp --input=trade.fbe --output=.)\n```\n\nAs the result 'fbe.h' and 'trade.h' files will be generated.\n\n## FastBinaryEncoding serialization methods\nFinally you should extend your domain model with a FastBinaryEncoding serialization\nmethods:\n\n```c++\n#include \"fbe/trade_models.h\"\n\n#include \u003calgorithm\u003e\n\nnamespace TradeProto {\n\nstruct Order\n{\n    ...\n\n    // FastBinaryEncoding serialization\n\n    template \u003cclass TBuffer\u003e\n    void Serialize(FBE::FieldModel\u003cTBuffer, trade::Order\u003e\u0026 model)\n    {\n        size_t model_begin = model.set_begin();\n        model.id.set(Id);\n        model.symbol.set(Symbol);\n        model.side.set((trade::OrderSide)Side);\n        model.type.set((trade::OrderType)Type);\n        model.price.set(Price);\n        model.volume.set(Volume);\n        model.set_end(model_begin);\n    }\n\n    template \u003cclass TBuffer\u003e\n    void Deserialize(const FBE::FieldModel\u003cTBuffer, trade::Order\u003e\u0026 model)\n    {\n        size_t model_begin = model.get_begin();\n        model.id.get(Id);\n        model.symbol.get(Symbol);\n        trade::OrderSide side;\n        model.side.get(side);\n        Side = (OrderSide)side;\n        trade::OrderType type;\n        model.type.get(type);\n        Type = (OrderType)type;\n        model.price.get(Price);\n        model.volume.get(Volume);\n        model.get_end(model_begin);\n    }\n\n    ...\n};\n\nstruct Balance\n{\n    ...\n\n    // FastBinaryEncoding serialization\n\n    template \u003cclass TBuffer\u003e\n    void Serialize(FBE::FieldModel\u003cTBuffer, trade::Balance\u003e\u0026 model)\n    {\n        size_t model_begin = model.set_begin();\n        model.currency.set(Currency);\n        model.amount.set(Amount);\n        model.set_end(model_begin);\n    }\n\n    template \u003cclass TBuffer\u003e\n    void Deserialize(const FBE::FieldModel\u003cTBuffer, trade::Balance\u003e\u0026 model)\n    {\n        size_t model_begin = model.get_begin();\n        model.currency.get(Currency);\n        model.amount.get(Amount);\n        model.get_end(model_begin);\n    }\n\n    ...\n};\n\nstruct Account\n{\n    ...\n\n    // FastBinaryEncoding serialization\n\n    template \u003cclass TBuffer\u003e\n    void Serialize(FBE::FieldModel\u003cTBuffer, trade::Account\u003e\u0026 model)\n    {\n        size_t model_begin = model.set_begin();\n        model.id.set(Id);\n        model.name.set(Name);\n        Wallet.Serialize(model.wallet);\n        auto order_model = model.orders.resize(Orders.size());\n        for (auto\u0026 order : Orders)\n        {\n            order.Serialize(order_model);\n            order_model.fbe_shift(order_model.fbe_size());\n        }\n        model.set_end(model_begin);\n    }\n\n    template \u003cclass TBuffer\u003e\n    void Deserialize(const FBE::FieldModel\u003cTBuffer, trade::Account\u003e\u0026 model)\n    {\n        size_t model_begin = model.get_begin();\n        model.id.get(Id);\n        model.name.get(Name);\n        Wallet.Deserialize(model.wallet);\n        Orders.clear();\n        for (size_t i = 0; i \u003c model.orders.size(); ++i)\n        {\n            Order order;\n            order.Deserialize(model.orders[i]);\n            Orders.emplace_back(order);\n        }\n        model.get_end(model_begin);\n    }\n\n    ...\n};\n\n} // namespace TradeProto\n```\n\n## FastBinaryEncoding example\nHere comes the usage example of FastBinaryEncoding serialize/deserialize functionality:\n\n```c++\n#include \"../proto/trade.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    TradeProto::Account account(1, \"Test\", \"USD\", 1000);\n    account.Orders.emplace_back(TradeProto::Order(1, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::MARKET, 1.23456, 1000));\n    account.Orders.emplace_back(TradeProto::Order(2, \"EURUSD\", TradeProto::OrderSide::SELL, TradeProto::OrderType::LIMIT, 1.0, 100));\n    account.Orders.emplace_back(TradeProto::Order(3, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::STOP, 1.5, 10));\n\n    // Serialize the account to the FBE stream\n    FBE::trade::AccountModel\u003cFBE::WriteBuffer\u003e writer;\n    size_t model_begin = writer.create_begin();\n    account.Serialize(writer.model);\n    size_t serialized = writer.create_end(model_begin);\n    assert(writer.verify() \u0026\u0026 \"Model is broken!\");\n\n    // Show original and FBE serialized sizes\n    std::cout \u003c\u003c \"Original size: \" \u003c\u003c account.size() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"FBE size: \" \u003c\u003c serialized \u003c\u003c std::endl;\n\n    // Deserialize the account from the FBE stream\n    TradeProto::Account deserialized;\n    FBE::trade::AccountModel\u003cFBE::ReadBuffer\u003e reader;\n    reader.attach(writer.buffer());\n    assert(reader.verify() \u0026\u0026 \"Model is broken!\");\n    deserialized.Deserialize(reader.model);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Id = \" \u003c\u003c deserialized.Id \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Name = \" \u003c\u003c deserialized.Name \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Currency = \" \u003c\u003c deserialized.Wallet.Currency \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Amount = \" \u003c\u003c deserialized.Wallet.Amount \u003c\u003c std::endl;\n    for (auto\u0026 order : deserialized.Orders)\n    {\n        std::cout \u003c\u003c \"Account.Order =\u003e Id: \" \u003c\u003c order.Id\n            \u003c\u003c \", Symbol: \" \u003c\u003c order.Symbol\n            \u003c\u003c \", Side: \" \u003c\u003c (int)order.Side\n            \u003c\u003c \", Type: \" \u003c\u003c (int)order.Type\n            \u003c\u003c \", Price: \" \u003c\u003c order.Price\n            \u003c\u003c \", Volume: \" \u003c\u003c order.Volume\n            \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nOutput of the example is the following:\n```\nOriginal size: 128\nFBE size: 234\n\nAccount.Id = 1\nAccount.Name = Test\nAccount.Wallet.Currency = USD\nAccount.Wallet.Amount = 1000\nAccount.Order =\u003e Id: 1, Symbol: EURUSD, Side: 0, Type: 0, Price: 1.23456, Volume: 1000\nAccount.Order =\u003e Id: 2, Symbol: EURUSD, Side: 1, Type: 1, Price: 1, Volume: 100\nAccount.Order =\u003e Id: 3, Symbol: EURUSD, Side: 0, Type: 2, Price: 1.5, Volume: 10\n```\n\n## FastBinaryEncoding performance\nFastBinaryEncoding serialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.644 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:23:18 2018\nUTC timestamp: Wed Jul 18 10:23:18 2018\n===============================================================================\nBenchmark: FastBinaryEncoding-Serialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: FastBinaryEncoding-Serialize\nAverage time: 66 ns/op\nMinimal time: 66 ns/op\nMaximal time: 67 ns/op\nTotal time: 3.598 s\nTotal operations: 54301046\nTotal bytes: 11.853 GiB\nOperations throughput: 15090301 ops/s\nBytes throughput: 3.295 GiB/s\nCustom values:\n        MessageSize: 234\n        OriginalSize: 128\n===============================================================================\n```\n\nFastBinaryEncoding deserialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.520 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:24:03 2018\nUTC timestamp: Wed Jul 18 10:24:03 2018\n===============================================================================\nBenchmark: FastBinaryEncoding-Deserialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: FastBinaryEncoding-Deserialize\nAverage time: 82 ns/op\nMinimal time: 82 ns/op\nMaximal time: 85 ns/op\nTotal time: 3.302 s\nTotal operations: 40260567\nTotal bytes: 8.792 GiB\nOperations throughput: 12190362 ops/s\nBytes throughput: 2.672 GiB/s\nCustom values:\n        MessageSize: 234\n        OriginalSize: 128\n===============================================================================\n```\n\n# FlatBuffers serialization\nFlatBuffers serialization is based on [FlatBuffers library](https://google.github.io/flatbuffers).\n\n## FlatBuffers schema\nFlatBuffers serialization starts with describing a model schema. For our domain\nmodel the schema will be the following:\n\n```proto\nnamespace Trade.flatbuf;\n\nenum OrderSide : byte\n{\n    buy,\n    sell\n}\n\nenum OrderType : byte\n{\n    market,\n    limit,\n    stop\n}\n\ntable Order\n{\n    id : int;\n    symbol : string;\n    side : OrderSide;\n    type : OrderType;\n    price : double = 0.0;\n    volume : double = 0.0;\n}\n\ntable Balance\n{\n    currency : string;\n    amount : double = 0.0;\n}\n\ntable Account\n{\n    id : int;\n    name : string;\n    wallet : Balance;\n    orders : [Order];\n}\n\nroot_type Account;\n```\n\n## FlatBuffers schema compilation\nThe next step is a schema compilation using 'flatc' utility which will create\na generated code for required programming language.\n\nThe following command will create a C++ generated code:\n```shell\nflatc --cpp --scoped-enums -o . trade.fbs\n```\n\nIt is possible to use add_custom_command() in CMakeLists.txt to generate code\nusing 'cmake' utility:\n```cmake\nadd_custom_command(TARGET example POST_BUILD COMMAND flatc --cpp --scoped-enums -o . trade.fbs)\n```\n\nAs the result 'domain_generated.h' file will be generated.\n\n## FlatBuffers serialization methods\nFinally you should extend your domain model with a FlatBuffers serialization\nmethods:\n\n```c++\n#include \"flatbuffers/trade_generated.h\"\n\n#include \u003calgorithm\u003e\n\nnamespace TradeProto {\n\nstruct Order\n{\n    ...\n\n    // FlatBuffers serialization\n\n    flatbuffers::Offset\u003cTrade::flatbuf::Order\u003e Serialize(flatbuffers::FlatBufferBuilder\u0026 builder)\n    {\n        return Trade::flatbuf::CreateOrderDirect(builder, Id, Symbol, (Trade::flatbuf::OrderSide)Side, (Trade::flatbuf::OrderType)Type, Price, Volume);\n    }\n\n    void Deserialize(const Trade::flatbuf::Order\u0026 value)\n    {\n        Id = value.id();\n        std::string symbol = value.symbol()-\u003estr();\n        std::memcpy(Symbol, symbol.c_str(), std::min(symbol.size() + 1, sizeof(Symbol)));\n        Side = (OrderSide)value.side();\n        Type = (OrderType)value.type();\n        Price = value.price();\n        Volume = value.volume();\n    }\n\n    ...\n};\n\nstruct Balance\n{\n    ...\n\n    // FlatBuffers serialization\n\n    flatbuffers::Offset\u003cTrade::flatbuf::Balance\u003e Serialize(flatbuffers::FlatBufferBuilder\u0026 builder)\n    {\n        return Trade::flatbuf::CreateBalanceDirect(builder, Currency, Amount);\n    }\n\n    void Deserialize(const Trade::flatbuf::Balance\u0026 value)\n    {\n        std::string currency = value.currency()-\u003estr();\n        std::memcpy(Currency, currency.c_str(), std::min(currency.size() + 1, sizeof(Currency)));\n        Amount = value.amount();\n    }\n\n    ...\n};\n\nstruct Account\n{\n    ...\n\n    // FlatBuffers serialization\n\n    flatbuffers::Offset\u003cTrade::flatbuf::Account\u003e Serialize(flatbuffers::FlatBufferBuilder\u0026 builder)\n    {\n        auto wallet = Wallet.Serialize(builder);\n        std::vector\u003cflatbuffers::Offset\u003cTrade::flatbuf::Order\u003e\u003e orders;\n        for (auto\u0026 order : Orders)\n            orders.emplace_back(order.Serialize(builder));\n        return Trade::flatbuf::CreateAccountDirect(builder, Id, Name.c_str(), wallet, \u0026orders);\n    }\n\n    void Deserialize(const Trade::flatbuf::Account\u0026 value)\n    {\n        Id = value.id();\n        Name = value.name()-\u003estr();\n        Wallet.Deserialize(*value.wallet());\n        Orders.clear();\n        for (auto o : *value.orders())\n        {\n            Order order;\n            order.Deserialize(*o);\n            Orders.emplace_back(order);\n        }\n    }\n\n    ...\n};\n\n} // namespace TradeProto\n```\n\n## FlatBuffers example\nHere comes the usage example of FlatBuffers serialize/deserialize functionality:\n\n```c++\n#include \"../proto/trade.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    TradeProto::Account account(1, \"Test\", \"USD\", 1000);\n    account.Orders.emplace_back(TradeProto::Order(1, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::MARKET, 1.23456, 1000));\n    account.Orders.emplace_back(TradeProto::Order(2, \"EURUSD\", TradeProto::OrderSide::SELL, TradeProto::OrderType::LIMIT, 1.0, 100));\n    account.Orders.emplace_back(TradeProto::Order(3, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::STOP, 1.5, 10));\n\n    // Serialize the account to the FlatBuffer stream\n    flatbuffers::FlatBufferBuilder builder;\n    builder.Finish(account.Serialize(builder));\n\n    // Show original and FlatBuffer serialized sizes\n    std::cout \u003c\u003c \"Original size: \" \u003c\u003c account.size() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"FlatBuffer size: \" \u003c\u003c builder.GetSize() \u003c\u003c std::endl;\n\n    // Deserialize the account from the FlatBuffer stream\n    TradeProto::Account deserialized;\n    deserialized.Deserialize(*Trade::flatbuf::GetAccount(builder.GetBufferPointer()));\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Id = \" \u003c\u003c deserialized.Id \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Name = \" \u003c\u003c deserialized.Name \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Currency = \" \u003c\u003c deserialized.Wallet.Currency \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Amount = \" \u003c\u003c deserialized.Wallet.Amount \u003c\u003c std::endl;\n    for (auto\u0026 order : deserialized.Orders)\n    {\n        std::cout \u003c\u003c \"Account.Order =\u003e Id: \" \u003c\u003c order.Id\n            \u003c\u003c \", Symbol: \" \u003c\u003c order.Symbol\n            \u003c\u003c \", Side: \" \u003c\u003c (int)order.Side\n            \u003c\u003c \", Type: \" \u003c\u003c (int)order.Type\n            \u003c\u003c \", Price: \" \u003c\u003c order.Price\n            \u003c\u003c \", Volume: \" \u003c\u003c order.Volume\n            \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nOutput of the example is the following:\n```\nOriginal size: 128\nFlatBuffer size: 280\n\nAccount.Id = 1\nAccount.Name = Test\nAccount.Wallet.Currency = USD\nAccount.Wallet.Amount = 1000\nAccount.Order =\u003e Id: 1, Symbol: EURUSD, Side: 0, Type: 0, Price: 1.23456, Volume: 1000\nAccount.Order =\u003e Id: 2, Symbol: EURUSD, Side: 1, Type: 1, Price: 1, Volume: 100\nAccount.Order =\u003e Id: 3, Symbol: EURUSD, Side: 0, Type: 2, Price: 1.5, Volume: 10\n```\n\n## FlatBuffers performance\nFlatBuffers serialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.624 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:24:57 2018\nUTC timestamp: Wed Jul 18 10:24:57 2018\n===============================================================================\nBenchmark: FlatBuffers-Serialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: FlatBuffers-Serialize\nAverage time: 830 ns/op\nMinimal time: 830 ns/op\nMaximal time: 840 ns/op\nTotal time: 4.830 s\nTotal operations: 5816587\nTotal bytes: 1.529 GiB\nOperations throughput: 1204142 ops/s\nBytes throughput: 321.553 MiB/s\nCustom values:\n        MessageSize: 280\n        OriginalSize: 128\n===============================================================================\n```\n\nFlatBuffers deserialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.631 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:25:45 2018\nUTC timestamp: Wed Jul 18 10:25:45 2018\n===============================================================================\nBenchmark: FlatBuffers-Deserialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: FlatBuffers-Deserialize\nAverage time: 290 ns/op\nMinimal time: 290 ns/op\nMaximal time: 293 ns/op\nTotal time: 4.690 s\nTotal operations: 16143136\nTotal bytes: 4.214 GiB\nOperations throughput: 3441995 ops/s\nBytes throughput: 919.114 MiB/s\nCustom values:\n        MessageSize: 280\n        OriginalSize: 128\n===============================================================================\n```\n\n# Protobuf serialization\nProtobuf serialization is based on [Protobuf library](https://developers.google.com/protocol-buffers).\n\n## Protobuf schema\nProtobuf serialization starts with describing a model schema. For our domain\nmodel the schema will be the following:\n\n```proto\nsyntax = \"proto3\";\npackage Trade.protobuf;\n\nenum OrderSide\n{\n    buy = 0;\n    sell = 1;\n}\n\nenum OrderType\n{\n    market = 0;\n    limit = 1;\n    stop = 2;\n}\n\nmessage Order\n{\n    int32 id = 1;\n    string symbol = 2;\n    OrderSide side = 3;\n    OrderType type = 4;\n    double price = 5;\n    double volume = 6;\n}\n\nmessage Balance\n{\n    string currency = 1;\n    double amount = 2;\n}\n\nmessage Account\n{\n    int32 id = 1;\n    string name = 2;\n    Balance wallet = 3;\n    repeated Order orders = 4;\n}\n```\n\n## Protobuf schema compilation\nThe next step is a schema compilation using 'protoc' utility which will create\na generated code for required programming language.\n\nThe following command will create a C++ generated code:\n```shell\nprotoc --proto_path=. --cpp_out=. trade.proto\n```\n\nIt is possible to use add_custom_command() in CMakeLists.txt to generate code\nusing 'cmake' utility:\n```cmake\nadd_custom_command(TARGET example POST_BUILD COMMAND protoc --proto_path=. --cpp_out=. trade.proto)\n```\n\nAs the result 'trade.pb.h' and 'trade.pb.cc' files will be generated.\n\n## Protobuf serialization methods\nFinally you should extend your domain model with a FlatBuffers serialization\nmethods:\n\n```c++\n#include \"protobuf/trade.pb.h\"\n\n#include \u003calgorithm\u003e\n\nnamespace TradeProto {\n\nstruct Order\n{\n    ...\n\n    // Protobuf serialization\n\n    Trade::protobuf::Order\u0026 Serialize(Trade::protobuf::Order\u0026 value)\n    {\n        value.set_id(Id);\n        value.set_symbol(Symbol);\n        value.set_side((Trade::protobuf::OrderSide)Side);\n        value.set_type((Trade::protobuf::OrderType)Type);\n        value.set_price(Price);\n        value.set_volume(Volume);\n        return value;\n    }\n\n    void Deserialize(const Trade::protobuf::Order\u0026 value)\n    {\n        Id = value.id();\n        std::string symbol = value.symbol();\n        std::memcpy(Symbol, symbol.c_str(), std::min(symbol.size() + 1, sizeof(Symbol)));\n        Side = (OrderSide)value.side();\n        Type = (OrderType)value.type();\n        Price = value.price();\n        Volume = value.volume();\n    }\n\n    ...\n};\n\nstruct Balance\n{\n    ...\n\n    // Protobuf serialization\n\n    Trade::protobuf::Balance\u0026 Serialize(Trade::protobuf::Balance\u0026 value)\n    {\n        value.set_currency(Currency);\n        value.set_amount(Amount);\n        return value;\n    }\n\n    void Deserialize(const Trade::protobuf::Balance\u0026 value)\n    {\n        std::string currency = value.currency();\n        std::memcpy(Currency, currency.c_str(), std::min(currency.size() + 1, sizeof(Currency)));\n        Amount = value.amount();\n    }\n\n    ...\n};\n\nstruct Account\n{\n    ...\n\n    // Protobuf serialization\n\n    Trade::protobuf::Account\u0026 Serialize(Trade::protobuf::Account\u0026 value)\n    {\n        value.set_id(id);\n        value.set_name(Name);\n        value.set_allocated_wallet(\u0026Wallet.Serialize(*value.wallet().New(value.GetArena())));\n        for (auto\u0026 order : Orders)\n            order.Serialize(*value.add_orders());\n        return value;\n    }\n\n    void Deserialize(const Trade::protobuf::Account\u0026 value)\n    {\n        Id = value.id();\n        Name = value.name();\n        Wallet.Deserialize(value.wallet());\n        Orders.clear();\n        for (int i = 0; i \u003c value.orders_size(); ++i)\n        {\n            Order order;\n            order.Deserialize(value.orders(i));\n            Orders.emplace_back(order);\n        }\n    }\n\n    ...\n};\n\n} // namespace TradeProto\n```\n\n## Protobuf example\nHere comes the usage example of Protobuf serialize/deserialize functionality:\n\n```c++\n#include \"../proto/trade.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    TradeProto::Account account(1, \"Test\", \"USD\", 1000);\n    account.Orders.emplace_back(TradeProto::Order(1, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::MARKET, 1.23456, 1000));\n    account.Orders.emplace_back(TradeProto::Order(2, \"EURUSD\", TradeProto::OrderSide::SELL, TradeProto::OrderType::LIMIT, 1.0, 100));\n    account.Orders.emplace_back(TradeProto::Order(3, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::STOP, 1.5, 10));\n\n    // Serialize the account to the Protobuf stream\n    Trade::protobuf::Account output;\n    account.Serialize(output);\n    auto buffer = output.SerializeAsString();\n\n    // Show original and Protobuf serialized sizes\n    std::cout \u003c\u003c \"Original size: \" \u003c\u003c account.size() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Protobuf size: \" \u003c\u003c buffer.size() \u003c\u003c std::endl;\n\n    // Deserialize the account from the Protobuf stream\n    Trade::protobuf::Account input;\n    input.ParseFromString(buffer);\n    TradeProto::Account deserialized;\n    deserialized.Deserialize(input);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Id = \" \u003c\u003c deserialized.Id \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Name = \" \u003c\u003c deserialized.Name \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Currency = \" \u003c\u003c deserialized.Wallet.Currency \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Amount = \" \u003c\u003c deserialized.Wallet.Amount \u003c\u003c std::endl;\n    for (auto\u0026 order : deserialized.Orders)\n    {\n        std::cout \u003c\u003c \"Account.Order =\u003e Id: \" \u003c\u003c order.Id\n            \u003c\u003c \", Symbol: \" \u003c\u003c order.Symbol\n            \u003c\u003c \", Side: \" \u003c\u003c (int)order.Side\n            \u003c\u003c \", Type: \" \u003c\u003c (int)order.Type\n            \u003c\u003c \", Price: \" \u003c\u003c order.Price\n            \u003c\u003c \", Volume: \" \u003c\u003c order.Volume\n            \u003c\u003c std::endl;\n    }\n\n    // Delete all global objects allocated by Protobuf\n    google::protobuf::ShutdownProtobufLibrary();\n\n    return 0;\n}\n```\n\nOutput of the example is the following:\n```\nOriginal size: 128\nProtobuf size: 120\n\nAccount.Id = 1\nAccount.Name = Test\nAccount.Wallet.Currency = USD\nAccount.Wallet.Amount = 1000\nAccount.Order =\u003e Id: 1, Symbol: EURUSD, Side: 0, Type: 0, Price: 1.23456, Volume: 1000\nAccount.Order =\u003e Id: 2, Symbol: EURUSD, Side: 1, Type: 1, Price: 1, Volume: 100\nAccount.Order =\u003e Id: 3, Symbol: EURUSD, Side: 0, Type: 2, Price: 1.5, Volume: 10\n```\n\n## Protobuf performance\nProtobuf serialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.676 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:26:34 2018\nUTC timestamp: Wed Jul 18 10:26:34 2018\n===============================================================================\nBenchmark: Protobuf-Serialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: Protobuf-Serialize\nAverage time: 628 ns/op\nMinimal time: 628 ns/op\nMaximal time: 658 ns/op\nTotal time: 4.552 s\nTotal operations: 7240754\nTotal bytes: 828.653 MiB\nOperations throughput: 1590357 ops/s\nBytes throughput: 182.002 MiB/s\nCustom values:\n        MessageSize: 120\n        OriginalSize: 128\n===============================================================================\n```\n\nProtobuf deserialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.676 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:27:18 2018\nUTC timestamp: Wed Jul 18 10:27:18 2018\n===============================================================================\nBenchmark: Protobuf-Deserialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: Protobuf-Deserialize\nAverage time: 759 ns/op\nMinimal time: 759 ns/op\nMaximal time: 776 ns/op\nTotal time: 4.757 s\nTotal operations: 6267474\nTotal bytes: 717.261 MiB\nOperations throughput: 1317322 ops/s\nBytes throughput: 150.773 MiB/s\nCustom values:\n        MessageSize: 120\n        OriginalSize: 128\n===============================================================================\n```\n\n# SimpleBinaryEncoding serialization\nSimpleBinaryEncoding serialization is based on [SimpleBinaryEncoding library](https://github.com/real-logic/simple-binary-encoding).\n\n## SimpleBinaryEncoding schema\nSimpleBinaryEncoding serialization starts with describing a model schema. For our\ndomain model the schema will be the following:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?\u003e\n\u003csbe:messageSchema xmlns:sbe=\"http://fixprotocol.io/2016/sbe\" package=\"sbe\" id=\"1\" version=\"1\" semanticVersion=\"5.2\" description=\"Trade schema\" byteOrder=\"littleEndian\"\u003e\n    \u003ctypes\u003e\n        \u003ccomposite name=\"messageHeader\" description=\"Message identifiers and length of message root\"\u003e\n            \u003ctype name=\"blockLength\" primitiveType=\"uint16\"/\u003e\n            \u003ctype name=\"templateId\" primitiveType=\"uint16\"/\u003e\n            \u003ctype name=\"schemaId\" primitiveType=\"uint16\"/\u003e\n            \u003ctype name=\"version\" primitiveType=\"uint16\"/\u003e\n        \u003c/composite\u003e\n        \u003ccomposite name=\"groupSizeEncoding\" description=\"Repeating group dimensions\"\u003e\n            \u003ctype name=\"blockLength\" primitiveType=\"uint16\"/\u003e\n            \u003ctype name=\"numInGroup\" primitiveType=\"uint16\"/\u003e\n        \u003c/composite\u003e\n        \u003ccomposite name=\"varStringEncoding\"\u003e\n            \u003ctype name=\"length\" primitiveType=\"uint32\" maxValue=\"1073741824\"/\u003e\n            \u003ctype name=\"varData\" primitiveType=\"uint8\" length=\"0\" characterEncoding=\"UTF-8\"/\u003e\n        \u003c/composite\u003e\n    \u003c/types\u003e\n    \u003ctypes\u003e\n        \u003cenum name=\"OrderSide\" encodingType=\"uint8\"\u003e\n            \u003cvalidValue name=\"buy\"\u003e0\u003c/validValue\u003e\n            \u003cvalidValue name=\"sell\"\u003e1\u003c/validValue\u003e\n        \u003c/enum\u003e\n        \u003cenum name=\"OrderType\" encodingType=\"uint8\"\u003e\n            \u003cvalidValue name=\"market\"\u003e0\u003c/validValue\u003e\n            \u003cvalidValue name=\"limit\"\u003e1\u003c/validValue\u003e\n            \u003cvalidValue name=\"stop\"\u003e2\u003c/validValue\u003e\n        \u003c/enum\u003e\n        \u003ccomposite name=\"Order\"\u003e\n            \u003ctype name=\"id\" primitiveType=\"int32\"/\u003e\n            \u003ctype name=\"symbol\" primitiveType=\"char\" length=\"10\" characterEncoding=\"UTF-8\"/\u003e\n            \u003cref name=\"side\" type=\"OrderSide\"/\u003e\n            \u003cref name=\"type\" type=\"OrderType\"/\u003e\n            \u003ctype name=\"price\" primitiveType=\"double\"/\u003e\n            \u003ctype name=\"volume\" primitiveType=\"double\"/\u003e\n        \u003c/composite\u003e\n        \u003ccomposite name=\"Balance\"\u003e\n            \u003ctype name=\"currency\" primitiveType=\"char\" length=\"10\" characterEncoding=\"UTF-8\"/\u003e\n            \u003ctype name=\"amount\" primitiveType=\"double\"/\u003e\n        \u003c/composite\u003e\n        \u003ctype name=\"AccountId\" primitiveType=\"int32\"/\u003e\n    \u003c/types\u003e\n    \u003csbe:message name=\"Account\" id=\"1\"\u003e\n        \u003cfield name=\"id\" id=\"1\" type=\"AccountId\"/\u003e\n        \u003cfield name=\"wallet\" id=\"2\" type=\"Balance\"/\u003e\n        \u003cgroup name=\"orders\" id=\"3\" dimensionType=\"groupSizeEncoding\"\u003e\n            \u003cfield name=\"order\" id=\"4\" type=\"Order\"/\u003e\n        \u003c/group\u003e\n        \u003cdata name=\"name\" id=\"5\" type=\"varStringEncoding\"/\u003e\n    \u003c/sbe:message\u003e\n\u003c/sbe:messageSchema\u003e\n```\n\n## SimpleBinaryEncoding schema compilation\nThe next step is a schema compilation using 'sbe' utility which will create\na generated code for required programming language.\n\nThe following command will create a C++ generated code:\n```shell\njava -Dsbe.target.language=cpp -jar sbe-all-1.29.0.jar trade.sbe.xml\n```\n\nAs the result required C++ header files will be generated.\n\n## SimpleBinaryEncoding serialization methods\nFinally you should extend your domain model with a SimpleBinaryEncoding serialization\nmethods:\n\n```c++\n#include \"fbe/trade_models.h\"\n\n#include \u003calgorithm\u003e\n\nnamespace TradeProto {\n\nstruct Order\n{\n    ...\n\n    // SimpleBinaryEncoding serialization\n\n    void Serialize(sbe::Order\u0026 model)\n    {\n        model.id(Id);\n        model.putSymbol(Symbol);\n        model.side((sbe::OrderSide::Value)Side);\n        model.type((sbe::OrderType::Value)Type);\n        model.price(Price);\n        model.volume(Volume);\n    }\n\n    void Deserialize(sbe::Order\u0026 model)\n    {\n        Id = model.id();\n        model.getSymbol(Symbol, sizeof(Symbol));\n        Side = (OrderSide)model.side();\n        Type = (OrderType)model.type();\n        Price = model.price();\n        Volume = model.volume();\n    }\n\n    ...\n};\n\nstruct Balance\n{\n    ...\n\n    // SimpleBinaryEncoding serialization\n\n    void Serialize(sbe::Balance\u0026 model)\n    {\n        model.putCurrency(Currency);\n        model.amount(Amount);\n    }\n\n    void Deserialize(sbe::Balance\u0026 model)\n    {\n        model.getCurrency(Currency, sizeof(Currency));\n        Amount = model.amount();\n    }\n\n    ...\n};\n\nstruct Account\n{\n    ...\n\n    // SimpleBinaryEncoding serialization\n\n    void Serialize(sbe::Account\u0026 model)\n    {\n        model.id(Id);\n        model.putName(Name);\n        Wallet.Serialize(model.wallet());\n        auto orders = model.ordersCount((uint16_t)Orders.size());\n        for (auto\u0026 order : Orders)\n            order.Serialize(orders.next().order());\n    }\n\n    void Deserialize(sbe::Account\u0026 model)\n    {\n        Id = model.id();\n        Name = model.getNameAsString();\n        Wallet.Deserialize(model.wallet());\n        Orders.clear();\n        auto orders = model.orders();\n        for (int i = 0; i \u003c orders.count(); ++i)\n        {\n            Order order;\n            order.Deserialize(orders.next().order());\n            Orders.emplace_back(order);\n        }\n    }\n\n    ...\n};\n\n} // namespace TradeProto\n```\n\n## SimpleBinaryEncoding example\nHere comes the usage example of SimpleBinaryEncoding serialize/deserialize functionality:\n\n```c++\n#include \"../proto/trade.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    TradeProto::Account account(1, \"Test\", \"USD\", 1000);\n    account.Orders.emplace_back(TradeProto::Order(1, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::MARKET, 1.23456, 1000));\n    account.Orders.emplace_back(TradeProto::Order(2, \"EURUSD\", TradeProto::OrderSide::SELL, TradeProto::OrderType::LIMIT, 1.0, 100));\n    account.Orders.emplace_back(TradeProto::Order(3, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::STOP, 1.5, 10));\n\n    // Serialize the account to the SBE stream\n    char buffer[1024];\n    sbe::MessageHeader header;\n    header.wrap(buffer, 0, 1, sizeof(buffer))\n       .blockLength(sbe::Account::sbeBlockLength())\n       .templateId(sbe::Account::sbeTemplateId())\n       .schemaId(sbe::Account::sbeSchemaId())\n       .version(sbe::Account::sbeSchemaVersion());\n    sbe::Account message;\n    message.wrapForEncode(buffer, header.encodedLength(), sizeof(buffer));\n    account.Serialize(message);\n\n    // Show original and SBE serialized sizes\n    std::cout \u003c\u003c \"Original size: \" \u003c\u003c account.size() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"SBE size: \" \u003c\u003c header.encodedLength() + message.encodedLength() \u003c\u003c std::endl;\n\n    // Deserialize the account from the SBE stream\n    header.wrap(buffer, 0, 1, sizeof(buffer));\n    int actingVersion = header.version();\n    int actingBlockLength = header.blockLength();\n    message.wrapForDecode(buffer, header.encodedLength(), actingBlockLength, actingVersion, sizeof(buffer));\n    TradeProto::Account deserialized;\n    deserialized.Deserialize(message);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Id = \" \u003c\u003c deserialized.Id \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Name = \" \u003c\u003c deserialized.Name \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Currency = \" \u003c\u003c deserialized.Wallet.Currency \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Amount = \" \u003c\u003c deserialized.Wallet.Amount \u003c\u003c std::endl;\n    for (auto\u0026 order : deserialized.Orders)\n    {\n        std::cout \u003c\u003c \"Account.Order =\u003e Id: \" \u003c\u003c order.Id\n            \u003c\u003c \", Symbol: \" \u003c\u003c order.Symbol\n            \u003c\u003c \", Side: \" \u003c\u003c (int)order.Side\n            \u003c\u003c \", Type: \" \u003c\u003c (int)order.Type\n            \u003c\u003c \", Price: \" \u003c\u003c order.Price\n            \u003c\u003c \", Volume: \" \u003c\u003c order.Volume\n            \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nOutput of the example is the following:\n```\nOriginal size: 128\nSBE size: 138\n\nAccount.Id = 1\nAccount.Name = Test\nAccount.Wallet.Currency = USD\nAccount.Wallet.Amount = 1000\nAccount.Order =\u003e Id: 1, Symbol: EURUSD, Side: 0, Type: 0, Price: 1.23456, Volume: 1000\nAccount.Order =\u003e Id: 2, Symbol: EURUSD, Side: 1, Type: 1, Price: 1, Volume: 100\nAccount.Order =\u003e Id: 3, Symbol: EURUSD, Side: 0, Type: 2, Price: 1.5, Volume: 10\n```\n\n## SimpleBinaryEncoding performance\nSimpleBinaryEncoding serialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 3.998 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.962 GiB\nRAM free: 16.910 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jan  2 05:34:26 2019\nUTC timestamp: Wed Jan  2 02:34:26 2019\n===============================================================================\nBenchmark: SimpleBinaryEncoding-Serialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: SimpleBinaryEncoding-Serialize\nAverage time: 35 ns/op\nMinimal time: 35 ns/op\nMaximal time: 38 ns/op\nTotal time: 2.398 s\nTotal operations: 67877907\nTotal bytes: 8.741 GiB\nOperations throughput: 28296533 ops/s\nBytes throughput: 3.652 GiB/s\nCustom values:\n        MessageSize: 138\n        OriginalSize: 128\n===============================================================================\n```\n\nSimpleBinaryEncoding deserialization performance of the provided domain model is the\nfollowing:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 3.998 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.962 GiB\nRAM free: 16.884 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jan  2 05:35:26 2019\nUTC timestamp: Wed Jan  2 02:35:26 2019\n===============================================================================\nBenchmark: SimpleBinaryEncoding-Deserialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: SimpleBinaryEncoding-Deserialize\nAverage time: 85 ns/op\nMinimal time: 85 ns/op\nMaximal time: 88 ns/op\nTotal time: 3.629 s\nTotal operations: 42653547\nTotal bytes: 5.493 GiB\nOperations throughput: 11750351 ops/s\nBytes throughput: 1.522 GiB/s\nCustom values:\n        MessageSize: 138\n        OriginalSize: 128\n===============================================================================\n```\n\n# JSON serialization\nJSON serialization is based on [RapidJSON library](http://rapidjson.org).\n\n## JSON serialization methods\nFinally you should extend your domain model with a JSON serialization\nmethods:\n\n```c++\n#include \"serialization/json/serializer.h\"\n#include \"serialization/json/deserializer.h\"\n\nnamespace TradeProto {\n\nstruct Order\n{\n    ...\n\n    // JSON serialization\n\n    template\u003ctypename OutputStream\u003e\n    void Serialize(CppSerialization::JSON::Serializer\u003cOutputStream\u003e\u0026 serializer)\n    {\n        serializer.StartObject();\n        serializer.Pair(\"id\", Id);\n        serializer.Pair(\"symbol\", Symbol);\n        serializer.Pair(\"side\", (int)Side);\n        serializer.Pair(\"type\", (int)Type);\n        serializer.Pair(\"price\", Price);\n        serializer.Pair(\"volume\", Volume);\n        serializer.EndObject();\n    }\n\n    template\u003ctypename JSON\u003e\n    void Deserialize(const JSON\u0026 json)\n    {\n        using namespace CppSerialization::JSON;\n\n        Deserializer::Find(json, \"id\", Id);\n        Deserializer::Find(json, \"symbol\", Symbol);\n        int side = 0; Deserializer::Find(json, \"side\", side); Side = (OrderSide)side;\n        int type = 0; Deserializer::Find(json, \"type\", type); Type = (OrderType)type;\n        Deserializer::Find(json, \"price\", Price);\n        Deserializer::Find(json, \"volume\", Volume);\n    }\n\n    ...\n};\n\nstruct Balance\n{\n    ...\n\n    // JSON serialization\n\n    template\u003ctypename OutputStream\u003e\n    void Serialize(CppSerialization::JSON::Serializer\u003cOutputStream\u003e\u0026 serializer)\n    {\n        serializer.StartObject();\n        serializer.Pair(\"currency\", Currency);\n        serializer.Pair(\"amount\", Amount);\n        serializer.EndObject();\n    }\n\n    template\u003ctypename JSON\u003e\n    void Deserialize(const JSON\u0026 json)\n    {\n        using namespace CppSerialization::JSON;\n\n        Deserializer::Find(json, \"currency\", Currency);\n        Deserializer::Find(json, \"amount\", Amount);\n    }\n\n    ...\n};\n\nstruct Account\n{\n    ...\n\n    // JSON serialization\n\n    template\u003ctypename OutputStream\u003e\n    void Serialize(CppSerialization::JSON::Serializer\u003cOutputStream\u003e\u0026 serializer)\n    {\n        serializer.StartObject();\n        serializer.Pair(\"id\", Id);\n        serializer.Pair(\"name\", Name);\n        serializer.Key(\"wallet\");\n        Wallet.Serialize(serializer);\n        serializer.Key(\"orders\");\n        serializer.StartArray();\n        for (auto\u0026 order : Orders)\n            order.Serialize(serializer);\n        serializer.EndArray();\n        serializer.EndObject();\n    }\n\n    template\u003ctypename JSON\u003e\n    void Deserialize(const JSON\u0026 json)\n    {\n        using namespace CppSerialization::JSON;\n\n        Deserializer::Find(json, \"id\", Id);\n        Deserializer::Find(json, \"name\", Name);\n        Deserializer::FindObject(json, \"wallet\", [this](const Value::ConstObject\u0026 object)\n        {\n            Wallet.Deserialize(object);\n        });\n        Orders.clear();\n        Deserializer::FindArray(json, \"orders\", [this](const Value\u0026 item)\n        {\n            Order order;\n            order.Deserialize(item);\n            Orders.emplace_back(order);\n        });\n    }\n\n    ...\n};\n\n} // namespace TradeProto\n```\n\n## JSON example\nHere comes the usage example of JSON serialize/deserialize functionality:\n\n```c++\n#include \"../proto/trade.h\"\n\n#include \"serialization/json/parser.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    TradeProto::Account account(1, \"Test\", \"USD\", 1000);\n    account.Orders.emplace_back(TradeProto::Order(1, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::MARKET, 1.23456, 1000));\n    account.Orders.emplace_back(TradeProto::Order(2, \"EURUSD\", TradeProto::OrderSide::SELL, TradeProto::OrderType::LIMIT, 1.0, 100));\n    account.Orders.emplace_back(TradeProto::Order(3, \"EURUSD\", TradeProto::OrderSide::BUY, TradeProto::OrderType::STOP, 1.5, 10));\n\n    // Serialize the account to the JSON stream\n    CppSerialization::JSON::StringBuffer buffer;\n    CppSerialization::JSON::Serializer\u003cCppSerialization::JSON::StringBuffer\u003e serializer(buffer);\n    account.Serialize(serializer);\n\n    // Show original and JSON serialized sizes\n    std::cout \u003c\u003c \"Original size: \" \u003c\u003c account.size() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"JSON content: \" \u003c\u003c buffer.GetString() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"JSON size: \" \u003c\u003c buffer.GetSize() \u003c\u003c std::endl;\n\n    // Parse JSON string\n    CppSerialization::JSON::Document json = CppSerialization::JSON::Parser::Parse(buffer.GetString());\n\n    // Deserialize the account from the JSON stream\n    TradeProto::Account deserialized;\n    deserialized.Deserialize(json);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Id = \" \u003c\u003c deserialized.Id \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Name = \" \u003c\u003c deserialized.Name \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Currency = \" \u003c\u003c deserialized.Wallet.Currency \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"Account.Wallet.Amount = \" \u003c\u003c deserialized.Wallet.Amount \u003c\u003c std::endl;\n    for (auto\u0026 order : deserialized.Orders)\n    {\n        std::cout \u003c\u003c \"Account.Order =\u003e Id: \" \u003c\u003c order.Id\n            \u003c\u003c \", Symbol: \" \u003c\u003c order.Symbol\n            \u003c\u003c \", Side: \" \u003c\u003c (int)order.Side\n            \u003c\u003c \", Type: \" \u003c\u003c (int)order.Type\n            \u003c\u003c \", Price: \" \u003c\u003c order.Price\n            \u003c\u003c \", Volume: \" \u003c\u003c order.Volume\n            \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nOutput of the example is the following:\n```\nOriginal size: 128\nJSON content: {\"id\":1,\"name\":\"Test\",\"wallet\":{\"currency\":\"USD\",\"amount\":1000.0},\"orders\":[{\"id\":1,\"symbol\":\"EURUSD\",\"side\":0,\"type\":0,\"price\":1.23456,\"volume\":1000.0},{\"id\":2,\"symbol\":\"EURUSD\",\"side\":1,\"type\":1,\"price\":1.0,\"volume\":100.0},{\"id\":3,\"symbol\":\"EURUSD\",\"side\":0,\"type\":2,\"price\":1.5,\"volume\":10.0}]}\nJSON size: 297\n\nAccount.Id = 1\nAccount.Name = Test\nAccount.Wallet.Currency = USD\nAccount.Wallet.Amount = 1000\nAccount.Order =\u003e Id: 1, Symbol: EURUSD, Side: 0, Type: 0, Price: 1.23456, Volume: 1000\nAccount.Order =\u003e Id: 2, Symbol: EURUSD, Side: 1, Type: 1, Price: 1, Volume: 100\nAccount.Order =\u003e Id: 3, Symbol: EURUSD, Side: 0, Type: 2, Price: 1.5, Volume: 10\n```\n\n## JSON performance\nJSON serialization performance of the provided domain model is the following:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.683 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:28:06 2018\nUTC timestamp: Wed Jul 18 10:28:06 2018\n===============================================================================\nBenchmark: JSON-Serialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: JSON-Serialize\nAverage time: 740 ns/op\nMinimal time: 740 ns/op\nMaximal time: 746 ns/op\nTotal time: 4.851 s\nTotal operations: 6552815\nTotal bytes: 1.857 GiB\nOperations throughput: 1350543 ops/s\nBytes throughput: 387.697 MiB/s\nCustom values:\n        MessageSize: 301\n        OriginalSize: 128\n===============================================================================\n```\n\nJSON document parsing performance of the provided domain model is the following:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.698 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:29:53 2018\nUTC timestamp: Wed Jul 18 10:29:53 2018\n===============================================================================\nBenchmark: JSON-Parse\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: JSON-Parse\nAverage time: 2.063 mcs/op\nMinimal time: 2.063 mcs/op\nMaximal time: 2.090 mcs/op\nTotal time: 4.928 s\nTotal operations: 2388728\nTotal bytes: 685.715 MiB\nOperations throughput: 484713 ops/s\nBytes throughput: 139.143 MiB/s\nCustom values:\n        MessageSize: 301\n===============================================================================\n```\n\nJSON deserialization performance of the provided domain model is the following:\n```\n===============================================================================\nCppBenchmark report. Version 1.0.0.0\n===============================================================================\nCPU architecutre: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz\nCPU logical cores: 8\nCPU physical cores: 4\nCPU clock speed: 4.008 GHz\nCPU Hyper-Threading: enabled\nRAM total: 31.903 GiB\nRAM free: 20.706 GiB\n===============================================================================\nOS version: Microsoft Windows 8 Enterprise Edition (build 9200), 64-bit\nOS bits: 64-bit\nProcess bits: 64-bit\nProcess configuaraion: release\nLocal timestamp: Wed Jul 18 13:30:43 2018\nUTC timestamp: Wed Jul 18 10:30:43 2018\n===============================================================================\nBenchmark: JSON-Deserialize\nAttempts: 5\nDuration: 5 seconds\n-------------------------------------------------------------------------------\nPhase: JSON-Deserialize\nAverage time: 500 ns/op\nMinimal time: 500 ns/op\nMaximal time: 510 ns/op\nTotal time: 4.749 s\nTotal operations: 9487106\nTotal bytes: 36.195 MiB\nOperations throughput: 1997556 ops/s\nBytes throughput: 7.634 MiB/s\nCustom values:\n        MessageSize: 301\n        OriginalSize: 128\n===============================================================================\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchronoxor%2Fcppserialization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchronoxor%2Fcppserialization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchronoxor%2Fcppserialization/lists"}