{"id":13595914,"url":"https://github.com/chronoxor/FastBinaryEncoding","last_synced_at":"2025-04-09T13:33:56.915Z","repository":{"id":43472568,"uuid":"145696528","full_name":"chronoxor/FastBinaryEncoding","owner":"chronoxor","description":"Fast Binary Encoding is ultra fast and universal serialization solution for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift","archived":false,"fork":false,"pushed_at":"2024-03-09T11:57:33.000Z","size":157175,"stargazers_count":906,"open_issues_count":45,"forks_count":93,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-04-03T10:11:11.022Z","etag":null,"topics":["binary","cpp","csharp","go","golang","java","javascript","kotlin","low-latency","performance","protocol","python","ruby","serialization","swift"],"latest_commit_sha":null,"homepage":"https://chronoxor.github.io/FastBinaryEncoding","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,"publiccode":null,"codemeta":null}},"created_at":"2018-08-22T10:58:01.000Z","updated_at":"2025-04-03T04:52:10.000Z","dependencies_parsed_at":"2024-05-02T01:04:42.815Z","dependency_job_id":null,"html_url":"https://github.com/chronoxor/FastBinaryEncoding","commit_stats":{"total_commits":935,"total_committers":11,"mean_commits":85.0,"dds":0.07807486631016047,"last_synced_commit":"93706503bb3e9056202b15b60ffc2e8d27426a99"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FFastBinaryEncoding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FFastBinaryEncoding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FFastBinaryEncoding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chronoxor%2FFastBinaryEncoding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chronoxor","download_url":"https://codeload.github.com/chronoxor/FastBinaryEncoding/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248049797,"owners_count":21039275,"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":["binary","cpp","csharp","go","golang","java","javascript","kotlin","low-latency","performance","protocol","python","ruby","serialization","swift"],"created_at":"2024-08-01T16:02:01.099Z","updated_at":"2025-04-09T13:33:53.818Z","avatar_url":"https://github.com/chronoxor.png","language":"C++","readme":"# Fast Binary Encoding (FBE)\n\n[![Awesome C++](https://awesome.re/badge.svg)](https://github.com/fffaraz/awesome-cpp)\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![Release](https://img.shields.io/github/release/chronoxor/FastBinaryEncoding.svg?sort=semver)](https://github.com/chronoxor/FastBinaryEncoding/releases)\n\u003cbr/\u003e\n[![Linux (clang)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-linux-clang.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-linux-clang.yml)\n[![Linux (gcc)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-linux-gcc.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-linux-gcc.yml)\n[![MacOS](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-macos.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-macos.yml)\n\u003cbr/\u003e\n[![Windows (Cygwin)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-cygwin.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-cygwin.yml)\n[![Windows (MSYS2)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-msys2.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-msys2.yml)\n[![Windows (MinGW)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-mingw.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-mingw.yml)\n[![Windows (Visual Studio)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-vs.yml/badge.svg)](https://github.com/chronoxor/FastBinaryEncoding/actions/workflows/build-windows-vs.yml)\n\nFast Binary Encoding allows to describe any domain models, business\nobjects, complex data structures, client/server requests \u0026 responses\nand generate native code for different programming languages and platforms.\n\n[Fast Binary Encoding documentation](https://chronoxor.github.io/FastBinaryEncoding)\u003cbr/\u003e\n[Fast Binary Encoding downloads](https://github.com/chronoxor/FastBinaryEncoding/releases)\u003cbr/\u003e\n[Fast Binary Encoding specification](https://chronoxor.github.io/FastBinaryEncoding/documents/FBE.html)\n\nPerformance comparison to other protocols can be found [here](https://github.com/chronoxor/CppSerialization):\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| [JSON](http://rapidjson.org)                                          |    301 bytes |             740 ns |               500 ns |\n\nTypical usage workflow is the following:\n1. [Create domain model](#create-domain-model) using base types, enums,\n   flags and structs\n2. [Generate domain model](#generate-domain-model) for any supported\n   programming languages (C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift)\n3. [Build domain model](#build-domain-model) library\n4. [Serialize/Deserialize](#fbe-serialization) objects from the domain model\n   in unified, fast and compact FastBinaryEncoding (FBE) format\n5. [JSON convert](#json-serialization) objects from the domain model in order\n   to use them in Web API\n6. Implement [Sender/Receiver interfaces](#senderreceiver-protocol) to create a communication protocol\n\nSample projects:\n* [C++ sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/examples)\n* [C# sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/CSharp)\n* [Go sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Go)\n* [Java sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Java)\n* [JavaScript sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/JavaScript)\n* [Kotlin sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Kotlin)\n* [Python sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Python)\n* [Ruby sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Ruby)\n* [Swift sample](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Swift)\n\n# Contents\n  * [Features](#features)\n  * [Requirements](#requirements)\n  * [How to build?](#how-to-build)\n  * [Create domain model](#create-domain-model)\n  * [Generate domain model](#generate-domain-model)\n  * [Build domain model](#build-domain-model)\n  * [FBE serialization](#fbe-serialization)\n  * [FBE final serialization](#fbe-final-serialization)\n  * [JSON serialization](#json-serialization)\n  * [Packages and import](#packages-and-import)\n  * [Struct keys](#struct-keys)\n  * [Struct numeration](#struct-numeration)\n  * [Struct inheritance](#struct-inheritance)\n  * [Versioning](#versioning)\n  * [Sender/Receiver protocol](#senderreceiver-protocol)\n  * [Performance benchmarks](#performance-benchmarks)\n    * [Benchmark 1: Serialization](#benchmark-1-serialization)\n    * [Benchmark 2: Deserialization](#benchmark-2-deserialization)\n    * [Benchmark 3: Verify](#benchmark-3-verify)\n\n# Features\n* Cross platform (Linux, MacOS, Windows)\n* [Generators for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift](#generate-domain-model)\n* [Fast binary encoding format](documents/FBE.md)\n* [Supported base types (byte, bool, char, wchar, int8, int16, int32, int64, float, double)](documents/FBE.md#base-types)\n* [Supported complex types (bytes, decimal, string, timestamp, uuid)](documents/FBE.md#complex-types)\n* [Supported collections (array, vector, list, map, hash)](documents/FBE.md#collections)\n* [Supported nullable optional types, enums, flags and structs](documents/FBE.md#optional-type)\n* [Serialization/Deserialization to/from binary format](#fbe-serialization)\n* [Serialization/Deserialization to/from JSON](#json-serialization)\n* [Sender/Receiver interfaces for communication protocols](#senderreceiver-protocol)\n* [Versioning solution](#versioning)\n* [Excellent performance](#performance-benchmarks)\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* [Cygwin](https://cygwin.com)\n* [MSYS2](https://www.msys2.org)\n* [MinGW](https://mingw-w64.org/doku.php)\n* [Visual Studio](https://www.visualstudio.com)\n* [WinFlexBison](https://github.com/lexxmark/winflexbison)\n\n# How to build?\n\n### Linux: install required packages\n```shell\nsudo apt-get install -y binutils-dev uuid-dev flex bison\n```\n\n### MacOS: install required packages\n```shell\nbrew install flex bison\n```\n\n### Windows: install required packages\n```shell\nchoco install winflexbison3\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/FastBinaryEncoding.git\ncd FastBinaryEncoding\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 (Cygwin)\n```shell\ncd build\nunix.bat\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# Create domain model\nTo use Fast Binary Encoding you should provide\na domain model (aka business objects). A domain model is a set of enums, flags\nand structures that relate to each other and might be aggregated in some\nhierarchy.\n\n[Fast Binary Encoding (FBE) format specification](documents/FBE.md)\n\nThere is a [sample domain model](https://github.com/chronoxor/FastBinaryEncoding/blob/master/proto/proto.fbe)\nwhich describes Account-Balance-Orders relation of some abstract trading\nplatform:\n\n```proto\n// Package declaration\npackage proto\n\n// Domain declaration\ndomain com.chronoxor\n\n// Order side declaration\nenum OrderSide : byte\n{\n    buy;\n    sell;\n}\n\n// Order type declaration\nenum OrderType : byte\n{\n    market;\n    limit;\n    stop;\n}\n\n// Order declaration\nstruct Order\n{\n    [key] int32 uid;\n    string symbol;\n    OrderSide side;\n    OrderType type;\n    double price = 0.0;\n    double volume = 0.0;\n}\n\n// Account balance declaration\nstruct Balance\n{\n    [key] string currency;\n    double amount = 0.0;\n}\n\n// Account state declaration\nflags State : byte\n{\n    unknown = 0x00;\n    invalid = 0x01;\n    initialized = 0x02;\n    calculated = 0x04;\n    broken = 0x08;\n    good = initialized | calculated;\n    bad = unknown | invalid | broken;\n}\n\n// Account declaration\nstruct Account\n{\n    [key] int32 uid;\n    string name;\n    State state = State.initialized | State.bad;\n    Balance wallet;\n    Balance? asset;\n    Order[] orders;\n}\n```\n\n# Generate domain model\nThe next step is a domain model compilation using 'fbec' compiler which will\ncreate a generated code for required programming language.\n\nThe following command will create a C++ generated code:\n```shell\nfbec --c++ --input=proto.fbe --output=.\n```\n\nAll possible options for the 'fbec' compiler are the following:\n```shell\nUsage: fbec [options]\n\nOptions:\n  --version             show program's version number and exit\n  -h, --help            show this help message and exit\n  -h HELP, --help=HELP  Show help\n  -i INPUT, --input=INPUT\n                        Input path\n  -o OUTPUT, --output=OUTPUT\n                        Output path\n  -q, --quiet           Launch in quiet mode. No progress will be shown!\n  -n INDENT, --indent=INDENT\n                        Format indent. Default: 0\n  -t, --tabs            Format with tabs. Default: off\n  --cpp                 Generate C++ code\n  --cpp-logging         Generate C++ logging code\n  --csharp              Generate C# code\n  --go                  Generate Go code\n  --java                Generate Java code\n  --javascript          Generate JavaScript code\n  --kotlin              Generate Kotlin code\n  --python              Generate Python code\n  --ruby                Generate Ruby code\n  --swift               Generate Swift code\n  --final               Generate Final serialization code\n  --json                Generate JSON serialization code\n  --proto               Generate Sender/Receiver protocol code\n```\n\n# Build domain model\nGenerated domain model is represented with source code for the particular language.\nJust add it to your project and build it.\nThere are several issues and dependencies that should be mentioned:\n\n### C++\n* C++ standard is limited to C++17 in order to have the implementation of\n  [std::optional](https://en.cppreference.com/w/cpp/utility/optional);\n* C++ has no native support for decimal type. Currently decimal type is\n  emulated with a double type. FBE does not use [GMPLib](https://gmplib.org)\n  because of heavy dependency in generated source code;\n* C++ formatting is supported with [{fmt}](https://fmt.dev) library of version\n  started from 9.0.0. Required include headers are `\u003cfmt/format.h\u003e` and\n  `\u003cfmt/ostream.h\u003e`;\n* JSON serialization is implemented using [RapidJSON](https://rapidjson.org)\n  library;\n\n### C#\n* JSON serialization is implemented using [Json.NET](https://www.newtonsoft.com/json) library.\n  Therefore it should be imported using NuGet;\n* Fast JSON serialization libraty is also available - [Utf8Json ](https://github.com/neuecc/Utf8Json).\n  If you want to try it, you should import is with NuGet and build domain model\n  with 'UTF8JSON' definition;\n\n### Go\n* Assert testing is based on [stretchr/testify](https://github.com/stretchr/testify) package (`go get github.com/stretchr/testify`);\n* JSON serialization is based on [jsoniter](https://github.com/json-iterator/go) package (`go get github.com/json-iterator/go`);\n* Decimal type is based on [shopspring/decimal](https://github.com/shopspring/decimal) package (`go get github.com/shopspring/decimal`);\n* UUID type is based on [google/uuid](https://github.com/google/uuid) package (`go get github.com/google/uuid`);\n\n### Java\n* JSON serialization is implemented using [Gson](https://github.com/google/gson) package.\n  Therefore it should be imported using Maven;\n\n### JavaScript\n* JavaScript domain model is implemented using [ECMAScript 6](http://es6-features.org)\n  (classes, etc.);\n* JSON serialization of set, map and hash types is limited to key with string type;\n\n### Kotlin\n* Starting from the version 1.3 [Kotlin supports unsigned integer numbers (UByte, UShort, UInt, ULong)](https://github.com/Kotlin/KEEP/blob/unsigned_types/proposals/unsigned-types.md).\n  This gives ability to represent FBE domain model more accurately than Java\n  language does;\n* JSON serialization is implemented using [Gson](https://github.com/google/gson) package.\n  Therefore it should be imported using Maven;\n\n### Python\n* Python 3.7 is required because of [time.time_ns()](https://docs.python.org/3/library/time.html#time.time_ns);\n\n### Ruby\n* Some Ruby dependencies should be installed from Gems:\n```shell\ngem install json\ngem install uuidtools\n```\n\n### Swift\n* Swift domain model is implemented using  uses [SwiftPM](https://github.com/apple/swift-package-manager) as its build tool;\n* JSON serialization is implemented using [Codable](https://developer.apple.com/documentation/swift/codable) protocol;\n* JSON serialization of set, map and hash types is limited to key with string type.\n\n# FBE serialization\nFast Binary Encoding (FBE) is a fast and compact binary format of representing\nsingle domain models in different programming languages and platforms.\nAlso FBE format [solves protocol versioning problem](#versioning).\n\nFollow the steps below in order to serialize any domain object:\n1. Create a new domain object and fill its fields and collections (*proto::Account account*);\n2. Create a domain model with a write buffer (*FBE::proto::AccountModel\u003cFBE::WriteBuffer\u003e writer*)\n3. Serialize the domain object into the domain model buffer (*writer.serialize(account)*)\n4. (Optional) Verify the domain object in the domain model buffer (*assert(writer.verify())*)\n5. Access the domain model buffer to store or send data (*writer.buffer()*)\n\nFollow the steps below in order to deserialize any domain object:\n1. Create a domain model with a read buffer (*FBE::proto::AccountModel\u003cFBE::ReadBuffer\u003e reader*)\n2. Attach a source buffer to the domain model (*reader.attach(writer.buffer())*)\n3. (Optional) Verify the domain object in the domain model buffer (*assert(reader.verify())*)\n4. Deserialize the domain object from the domain model buffer (*reader.deserialize(account)*)\n\nHere is an exmple of FBE serialization in C++ language:\n```c++\n#include \"../proto/proto_models.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    proto::Account account = { 1, \"Test\", proto::State::good, { \"USD\", 1000.0 }, std::make_optional\u003cproto::Balance\u003e({ \"EUR\", 100.0 }), {} };\n    account.orders.emplace_back(1, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);\n    account.orders.emplace_back(2, \"EURUSD\", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);\n    account.orders.emplace_back(3, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);\n\n    // Serialize the account to the FBE stream\n    FBE::proto::AccountModel\u003cFBE::WriteBuffer\u003e writer;\n    writer.serialize(account);\n    assert(writer.verify());\n\n    // Show the serialized FBE size\n    std::cout \u003c\u003c \"FBE size: \" \u003c\u003c writer.buffer().size() \u003c\u003c std::endl;\n\n    // Deserialize the account from the FBE stream\n    FBE::proto::AccountModel\u003cFBE::ReadBuffer\u003e reader;\n    reader.attach(writer.buffer());\n    assert(reader.verify());\n    reader.deserialize(account);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c account;\n\n    return 0;\n}\n```\n\nOutput is the following:\n```\nFBE size: 252\n\nAccount(\n  uid=1,\n  name=\"Test\",\n  state=initialized|calculated|good,\n  wallet=Balance(currency=\"USD\",amount=1000),\n  asset=Balance(currency=\"EUR\",amount=100),\n  orders=[3][\n    Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000),\n    Order(uid=2,symbol=\"EURUSD\",side=sell,type=limit,price=1,volume=100),\n    Order(uid=3,symbol=\"EURUSD\",side=buy,type=stop,price=1.5,volume=10)\n  ]\n)\n```\n\n# FBE final serialization\nIt is possible to achieve more serialization speed if your protocol is mature\nenough so you can fix its final version and disable [versioning](#versioning)\nwhich requires extra size and time to process.\n\n| Protocol  | Message size | Serialization time | Deserialization time | Verify time |\n| :-------: | -----------: | -----------------: | -------------------: | ----------: |\n| FBE       |    252 bytes |              88 ns |                98 ns |       33 ns |\n| FBE final |    152 bytes |              57 ns |                81 ns |       28 ns |\n\nFinal domain model can be compiled with [--final](#generate-domain-model) flag.\nAs the result additional final models will be available for serialization.\n\nFollow the steps below in order to serialize any domain object in final format:\n1. Create a new domain object and fill its fields and collections (*proto::Account account*);\n2. Create a domain final model with a write buffer (*FBE::proto::AccountFinalModel\u003cFBE::WriteBuffer\u003e writer*)\n3. Serialize the domain object into the domain model buffer (*writer.serialize(account)*)\n4. (Optional) Verify the domain object in the domain model buffer (*assert(writer.verify())*)\n5. Access the domain model buffer to store or send data (*writer.buffer()*)\n\nFollow the steps below in order to deserialize any domain object:\n1. Create a domain final model with a read buffer (*FBE::proto::AccountFinalModel\u003cFBE::ReadBuffer\u003e reader*)\n2. Attach a source buffer to the domain final model (*reader.attach(writer.buffer())*)\n3. (Optional) Verify the domain object in the domain model buffer (*assert(reader.verify())*)\n4. Deserialize the domain object from the domain model buffer (*reader.deserialize(account)*)\n\nHere is an exmple of FBE final serialization in C++ language:\n```c++\n#include \"../proto/proto_models.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    proto::Account account = { 1, \"Test\", proto::State::good, { \"USD\", 1000.0 }, std::make_optional\u003cproto::Balance\u003e({ \"EUR\", 100.0 }), {} };\n    account.orders.emplace_back(1, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);\n    account.orders.emplace_back(2, \"EURUSD\", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);\n    account.orders.emplace_back(3, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);\n\n    // Serialize the account to the FBE stream\n    FBE::proto::AccountFinalModel\u003cFBE::WriteBuffer\u003e writer;\n    writer.serialize(account);\n    assert(writer.verify());\n\n    // Show the serialized FBE size\n    std::cout \u003c\u003c \"FBE final size: \" \u003c\u003c writer.buffer().size() \u003c\u003c std::endl;\n\n    // Deserialize the account from the FBE stream\n    FBE::proto::AccountFinalModel\u003cFBE::ReadBuffer\u003e reader;\n    reader.attach(writer.buffer());\n    assert(reader.verify());\n    reader.deserialize(account);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c account;\n\n    return 0;\n}\n```\n\nOutput is the following:\n```\nFBE final size: 152\n\nAccount(\n  uid=1,\n  name=\"Test\",\n  state=initialized|calculated|good,\n  wallet=Balance(currency=\"USD\",amount=1000),\n  asset=Balance(currency=\"EUR\",amount=100),\n  orders=[3][\n    Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000),\n    Order(uid=2,symbol=\"EURUSD\",side=sell,type=limit,price=1,volume=100),\n    Order(uid=3,symbol=\"EURUSD\",side=buy,type=stop,price=1.5,volume=10)\n  ]\n)\n```\n\n# JSON serialization\nIf the domain model compiled with [--json](#generate-domain-model) flag,\nthen JSON serialization code will be generated in all domain objects.\nAs the result each domain object can be serialized/deserialized into/from\n[JSON format](https://www.json.org).\n\nPlease note that some programming languages have native JSON support\n(JavaScript, Python). Other languages requires third-party library\nto get work with JSON:\n* C++ requires [RapidJSON](http://rapidjson.org) library\n* C# requires [Json.NET](https://www.newtonsoft.com/json) package or more faster [Utf8Json](https://github.com/neuecc/Utf8Json) package\n* Go requires [jsoniter](https://github.com/json-iterator/go) package\n* Java and Kotlin requires [Gson](https://github.com/google/gson) package\n* Ruby requires [json](https://rubygems.org/gems/json) gem\n\nHere is an exmple of JSON serialization in C++ language:\n```c++\n#include \"../proto/proto.h\"\n\n#include \u003ciostream\u003e\n\nint main(int argc, char** argv)\n{\n    // Create a new account with some orders\n    proto::Account account = { 1, \"Test\", proto::State::good, { \"USD\", 1000.0 }, std::make_optional\u003cproto::Balance\u003e({ \"EUR\", 100.0 }), {} };\n    account.orders.emplace_back(1, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);\n    account.orders.emplace_back(2, \"EURUSD\", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);\n    account.orders.emplace_back(3, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);\n\n    // Serialize the account to the JSON stream\n    rapidjson::StringBuffer buffer;\n    rapidjson::Writer\u003crapidjson::StringBuffer\u003e writer(buffer);\n    FBE::JSON::to_json(writer, account);\n\n    // Show the serialized JSON and its size\n    std::cout \u003c\u003c \"JSON: \" \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 the JSON document\n    rapidjson::Document json;\n    json.Parse(buffer.GetString());\n\n    // Deserialize the account from the JSON stream\n    FBE::JSON::from_json(json, account);\n\n    // Show account content\n    std::cout \u003c\u003c std::endl;\n    std::cout \u003c\u003c account;\n\n    return 0;\n}\n```\n\nOutput is the following:\n```\nJSON: {\n  \"uid\":1,\n  \"name\":\n  \"Test\",\n  \"state\":6,\n  \"wallet\":{\"currency\":\"USD\",\"amount\":1000.0},\n  \"asset\":{\"currency\":\"EUR\",\"amount\":100.0},\n  \"orders\":[\n    {\"uid\":1,\"symbol\":\"EURUSD\",\"side\":0,\"type\":0,\"price\":1.23456,\"volume\":1000.0},\n    {\"uid\":2,\"symbol\":\"EURUSD\",\"side\":1,\"type\":1,\"price\":1.0,\"volume\":100.0},\n    {\"uid\":3,\"symbol\":\"EURUSD\",\"side\":0,\"type\":2,\"price\":1.5,\"volume\":10.0}\n  ]\n}\nJSON size: 353\n\nAccount(\n  uid=1,\n  name=\"Test\",\n  state=initialized|calculated|good,\n  wallet=Balance(currency=\"USD\",amount=1000),\n  asset=Balance(currency=\"EUR\",amount=100),\n  orders=[3][\n    Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000),\n    Order(uid=2,symbol=\"EURUSD\",side=sell,type=limit,price=1,volume=100),\n    Order(uid=3,symbol=\"EURUSD\",side=buy,type=stop,price=1.5,volume=10)\n  ]\n)\n```\n\n# Packages and import\nPackages are declared with package name and structs offset (optional). Offset\nwill be add to incremented structure type if is was not provided explicit.\n\nHere is an example of the simple package declaration:\n```proto\n// Package declaration. Offset is 0.\npackage proto\n\n// Struct type number is 1 (proto offset 0 + 1)\nstruct Struct1\n{\n    ...\n}\n\n// Struct type number is 2 (proto offset 0 + 2)\nstruct Struct2\n{\n    ...\n}\n```\n\nOne package can be imported into another and all enums, flags and structs can\nbe reused in the current package. Package offset is used here to avoid structs\ntypes intersection:\n```proto\n// Package declaration. Offset is 10.\npackage protoex offset 10\n\n// Package import\nimport proto\n\n// Struct type number is 11 (protoex offset 10 + 1)\nstruct Struct11\n{\n    // Struct1 is reused form the imported package\n    proto.Struct1 s1;\n    ...\n}\n\n// Struct type number is 12 (protoex offset 10 + 2)\nstruct Struct12\n{\n    ...\n}\n```\n\nMultiple package import is possible as well:\n```proto\n// Package declaration. Offset is 100.\npackage test offset 100\n\n// Package import\nimport proto\nimport protoex\n\n...\n```\n\nPackage import is implemented using:\n* #include \"...\" directive in C++\n* Namespaces in C#\n* Packages in Go\n* Packages in Java and Kotlin\n* Modules in JavaScript\n* Modules in Python\n* Ruby require statement\n\n# Struct keys\nSome of struct fileds (one or many) can be marked with '[key]' attribute. As\nthe result corresponding compare operators will be generated which allow to\ncompare two instances of the struct (equality, ordering, hashing) by marked\nfields. This ability allows to use the struct as a key in associative map and\nhash containers.\n\nExample below demonstrates the usage of '[key]' attribute:\n```proto\nstruct MyKeyStruct\n{\n    [key] int32 uid;\n    [key] stirng login;\n    string name;\n    string address;\n}\n```\n\nAfter code generation for C++ language the following comparable class will be\ngenerated:\n```c++\nstruct MyKeyStruct\n{\n    int32_t uid;\n    ::sample::stirng login;\n    std::string name;\n    std::string address;\n\n    ...\n\n    bool operator==(const MyKeyStruct\u0026 other) const noexcept\n    {\n        return (\n            (uid == other.uid)\n            \u0026\u0026 (login == other.login)\n            );\n    }\n    bool operator!=(const MyKeyStruct\u0026 other) const noexcept { return !operator==(other); }\n    bool operator\u003c(const MyKeyStruct\u0026 other) const noexcept\n    {\n        if (uid \u003c other.uid)\n            return true;\n        if (other.uid \u003c uid)\n            return false;\n        if (login \u003c other.login)\n            return true;\n        if (other.login \u003c login)\n            return false;\n        return false;\n    }\n    bool operator\u003c=(const MyKeyStruct\u0026 other) const noexcept { return operator\u003c(other) || operator==(other); }\n    bool operator\u003e(const MyKeyStruct\u0026 other) const noexcept { return !operator\u003c=(other); }\n    bool operator\u003e=(const MyKeyStruct\u0026 other) const noexcept { return !operator\u003c(other); }\n\n    ...\n};\n```\n\n# Struct numeration\nStruct type numbers are automatically increased until you provide it manually.\nThere are two possibilities:\n1. Shift the current struct type number using '(+X)' suffix. As the result\n   all new structs will have incremented type.\n2. Force set struct type number using '(X)' of '(base)' suffix. It will\n   affect only one struct.\n\nExample below demonstrates the idea:\n```proto\n// Package declaration. Offset is 0.\npackage proto\n\n// Struct type number is 1 (implicit declared)\nstruct Struct1\n{\n    ...\n}\n\n// Struct type number is 2 (implicit declared)\nstruct Struct2\n{\n    ...\n}\n\n// Struct type number is 10 (explicit declared, shifted to 10)\nstruct Struct10(+10)\n{\n    ...\n}\n\n// Struct type number is 11 (implicit declared)\nstruct Struct11\n{\n    ...\n}\n\n// Struct type number is 100 (explicit declared, forced to 100)\nstruct Struct100(100)\n{\n    ...\n}\n\n// Struct type number is 12 (implicit declared)\nstruct Struct12\n{\n    ...\n}\n```\n\n# Struct inheritance\nStructs can be inherited from another struct. In this case all fields from the\nbase struct will be present in a child one.\n```proto\npackage proto\n\n// Struct type number is 1\nstruct StructBase\n{\n    bool f1;\n    int8 f2;\n}\n\n// Struct type number is 2\nstruct StructChild : StructBase\n{\n    // bool f1 - will be inherited from StructBase\n    // int8 f2 - will be inherited from StructBase\n    int16 f3;\n    int32 f4;\n}\n```\n\nAlso it is possible to reuse the base struct type number in a child one using\n'= base' operator. It is useful when you extend the struct from third-party\nimported package:\n```proto\n// Package declaration. Offset is 10.\npackage protoex offset 10\n\n// Package import\nimport proto\n\n// Struct type number is 1\nstruct StructChild(base) : proto.StructBase\n{\n    // bool f1 - will be inherited from proto.StructBase\n    // int8 f2 - will be inherited from proto.StructBase\n    int16 f3;\n    int32 f4;\n}\n```\n\n# Versioning\nVersioning is simple with Fast Binary Encoding.\n\nAssume you have an original protocol:\n```proto\npackage proto\n\nenum MyEnum\n{\n    value1;\n    value2;\n}\n\nflags MyFlags\n{\n    none = 0x00;\n    flag1 = 0x01;\n    flag2 = 0x02;\n    flag3 = 0x04;\n}\n\nstruct MyStruct\n{\n    bool field1;\n    byte field2;\n    char field3;\n}\n```\n\nYou need to extend it with new enum, flag and struct values. Just add required\nvalues to the end of the corresponding declarations:\n```proto\npackage proto\n\nenum MyEnum\n{\n    value1;\n    value2;\n    value3; // New value\n    value4; // New value\n}\n\nflags MyFlags\n{\n    none = 0x00;\n    flag1 = 0x01;\n    flag2 = 0x02;\n    flag3 = 0x04;\n    flag4 = 0x08; // New value\n    flag5 = 0x10; // New value\n}\n\nstruct MyStruct\n{\n    bool field1;\n    byte field2;\n    char field3;\n    int32 field4;          // New field (default value is 0)\n    int64 field5 = 123456; // New field (default value is 123456)\n}\n```\n\nNow you can serialize and deserialize structs in different combinations:\n* Serialize old, deserialize old - nothing will be lost (best case);\n* Serialize old, deserialize new - all old fields will be deserialized, all new\n  fields will be initialized with 0 or default values according to definition;\n* Serialize new, deserialize old - all old fields will be deserialized, all new\n  fields will be discarded;\n* Serialize new, deserialize new - nothing will be lost (best case);\n\n### Versioning of the third-party protocol\nIf you are not able to modify some third-party protocol, you can still have a\nsolution of extending it. Just create a new protocol and import third-party\none into it. Then extend structs with inheritance:\n```proto\npackage protoex\n\nimport proto\n\nstruct MyStructEx(base) : proto.MyStruct\n{\n    int32 field4;          // New field (default value is 0)\n    int64 field5 = 123456; // New field (default value is 123456)\n}\n```\n\n# Sender/Receiver protocol\nIf the domain model compiled with [--sender](#generate-domain-model) flag,\nthen Sender/Receiver protocol code will be generated.\n\nSender interface contains 'send(struct)' methods for all domain model structs.\nAlso it has abstract 'onSend(data, size)' method which should be implemented\nto send serialized data to a socket, pipe, etc.\n\nReceiver interface contains 'onReceive(struct)' handlers for all domain\nmodel structs. Also it has public 'onReceive(type, data, size)' method\nwhich should be used to feed the Receiver with received data from a socket,\npipe, etc.\n\nHere is an exmple of using Sender/Receiver communication protocol in C++ language:\n```c++\n#include \"../proto/proto_protocol.h\"\n\n#include \u003ciostream\u003e\n\nclass MySender : public FBE::proto::Sender\u003cFBE::WriteBuffer\u003e\n{\nprotected:\n    size_t onSend(const void* data, size_t size) override\n    {\n        // Send nothing...\n        return 0;\n    }\n\n    void onSendLog(const std::string\u0026 message) const override\n    {\n        std::cout \u003c\u003c \"onSend: \" \u003c\u003c message \u003c\u003c std::endl;\n    }\n};\n\nclass MyReceiver : public FBE::proto::Receiver\u003cFBE::WriteBuffer\u003e\n{\nprotected:\n    void onReceive(const proto::Order\u0026 value) override {}\n    void onReceive(const proto::Balance\u0026 value) override {}\n    void onReceive(const proto::Account\u0026 value) override {}\n\n    void onReceiveLog(const std::string\u0026 message) const override\n    {\n        std::cout \u003c\u003c \"onReceive: \" \u003c\u003c message \u003c\u003c std::endl;\n    }\n};\n\nint main(int argc, char** argv)\n{\n    MySender sender;\n\n    // Enable logging\n    sender.logging(true);\n\n    // Create and send a new order\n    proto::Order order = { 1, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0 };\n    sender.send(order);\n\n    // Create and send a new balance wallet\n    proto::Balance balance = { \"USD\", 1000.0 };\n    sender.send(balance);\n\n    // Create and send a new account with some orders\n    proto::Account account = { 1, \"Test\", proto::State::good, { \"USD\", 1000.0 }, std::make_optional\u003cproto::Balance\u003e({ \"EUR\", 100.0 }), {} };\n    account.orders.emplace_back(1, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::market, 1.23456, 1000.0);\n    account.orders.emplace_back(2, \"EURUSD\", proto::OrderSide::sell, proto::OrderType::limit, 1.0, 100.0);\n    account.orders.emplace_back(3, \"EURUSD\", proto::OrderSide::buy, proto::OrderType::stop, 1.5, 10.0);\n    sender.send(account);\n\n    MyReceiver receiver;\n\n    // Enable logging\n    receiver.logging(true);\n\n    // Receive all data from the sender\n    receiver.receive(sender.buffer().data(), sender.buffer().size());\n\n    return 0;\n}\n```\n\nOutput is the following:\n```\nonSend: Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000)\nonSend: Balance(currency=\"USD\",amount=1000)\nonSend: Account(uid=1,name=\"Test\",state=initialized|calculated|good,wallet=Balance(currency=\"USD\",amount=1000),asset=Balance(currency=\"EUR\",amount=100),orders=[3][Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000),Order(uid=2,symbol=\"EURUSD\",side=sell,type=limit,price=1,volume=100),Order(uid=3,symbol=\"EURUSD\",side=buy,type=stop,price=1.5,volume=10)])\nonReceive: Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000)\nonReceive: Balance(currency=\"USD\",amount=1000)\nonReceive: Account(uid=1,name=\"Test\",state=initialized|calculated|good,wallet=Balance(currency=\"USD\",amount=1000),asset=Balance(currency=\"EUR\",amount=100),orders=[3][Order(uid=1,symbol=\"EURUSD\",side=buy,type=market,price=1.23456,volume=1000),Order(uid=2,symbol=\"EURUSD\",side=sell,type=limit,price=1,volume=100),Order(uid=3,symbol=\"EURUSD\",side=buy,type=stop,price=1.5,volume=10)])\n```\n\n# Performance benchmarks\nAll benchmarks use the same [domain model](#create-domain-model) to create a\nsingle account with three orders:\n```c++\nAccount account = { 1, \"Test\", State::good, { \"USD\", 1000.0 }, std::make_optional\u003cBalance\u003e({ \"EUR\", 100.0 }), {} };\naccount.orders.emplace_back(1, \"EURUSD\", OrderSide::buy, OrderType::market, 1.23456, 1000.0);\naccount.orders.emplace_back(2, \"EURUSD\", OrderSide::sell, OrderType::limit, 1.0, 100.0);\naccount.orders.emplace_back(3, \"EURUSD\", OrderSide::buy, OrderType::stop, 1.5, 10.0);\n```\n\n* [C++ benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/performance) results were taken using [CppBenchmark library](https://github.com/chronoxor/CppBenchmark)\n* [C# benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/CSharp/Benchmarks) results were taken using [BenchmarkDotNet library](https://benchmarkdotnet.org)\n* [Go benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Go/benchmarks) results were taken using [testing package](https://golang.org/pkg/testing)\n* [Java benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Java/src/benchmarks) results were taken using [JMH library](http://openjdk.java.net/projects/code-tools/jmh)\n* [JavaScript benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/JavaScript/benchmarks) results were taken using [Benchmark.js library](https://benchmarkjs.com)\n* [Kotlin benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Kotlin/src/benchmarks) results were taken using [JMH library](http://openjdk.java.net/projects/code-tools/jmh)\n* [Python benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Python/benchmarks) results were taken using [timeit module](https://docs.python.org/3/library/timeit.html)\n* [Ruby benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Ruby/benchmarks) results were taken using [Benchmark module](http://ruby-doc.org/stdlib/libdoc/benchmark/rdoc/Benchmark.html)\n* [Swift benchmarks](https://github.com/chronoxor/FastBinaryEncoding/tree/master/projects/Swift/Tests/Benchmark) results were taken using [XCTest framework](https://developer.apple.com/documentation/xctest/xctestcase/1496290-measure)\n\n## Benchmark 1: Serialization\nSerialization benchmark C++ code:\n```c++\nBENCHMARK_FIXTURE(SerializationFixture, \"Serialize\")\n{\n    // Reset FBE stream\n    writer.reset();\n\n    // Serialize the account to the FBE stream\n    writer.serialize(account);\n}\n```\n\nSerialization benchmark results:\n\n| Language \u0026 Platform      | Message size | Serialization rate | Serialization time |\n| :----------------------- | -----------: | -----------------: | -----------------: |\n| C++ Win64                |    252 bytes |   10 416 667 ops/s |              96 ns |\n| C++ Win64 (Final)        |    152 bytes |   16 129 032 ops/s |              62 ns |\n| C++ Win64 (JSON)         |    353 bytes |      926 784 ops/s |           1 079 ns |\n| C# Win64                 |    252 bytes |    1 432 665 ops/s |             698 ns |\n| C# Win64 (Final)         |    152 bytes |    1 597 444 ops/s |             626 ns |\n| C# Win64 (JSON)          |    341 bytes |      434 783 ops/s |           2 300 ns |\n| Go Win64                 |    252 bytes |    2 739 726 ops/s |             365 ns |\n| Go Win64 (Final)         |    152 bytes |    2 949 852 ops/s |             339 ns |\n| Go Win64 (JSON)          |    341 bytes |      258 732 ops/s |           3 865 ns |\n| Java Win64               |    252 bytes |    4 247 162 ops/s |             236 ns |\n| Java Win64 (Final)       |    152 bytes |    4 883 205 ops/s |             205 ns |\n| Java Win64 (JSON)        |    353 bytes |      213 983 ops/s |           4 673 ns |\n| JavaScript Win64         |    252 bytes |       93 416 ops/s |          10 705 ns |\n| JavaScript Win64 (Final) |    152 bytes |      112 665 ops/s |           8 876 ns |\n| JavaScript Win64 (JSON)  |    341 bytes |      217 637 ops/s |           4 595 ns |\n| Kotlin Win64             |    252 bytes |    3 546 694 ops/s |             282 ns |\n| Kotlin Win64 (Final)     |    152 bytes |    4 096 406 ops/s |             244 ns |\n| Kotlin Win64 (JSON)      |    353 bytes |      185 788 ops/s |           5 382 ns |\n| Python Win64             |    252 bytes |        9 434 ops/s |         105 999 ns |\n| Python Win64 (Final)     |    152 bytes |       11 635 ops/s |          85 945 ns |\n| Python Win64 (JSON)      |    324 bytes |       61 737 ops/s |          16 198 ns |\n| Ruby Win64               |    252 bytes |       23 013 ops/s |          43 453 ns |\n| Ruby Win64 (Final)       |    152 bytes |       33 361 ops/s |          29 975 ns |\n| Ruby Win64 (JSON)        |    353 bytes |       50 842 ops/s |          19 669 ns |\n| Swift macOS              |    252 bytes |       74 002 ops/s |          13 513 ns |\n| Swift macOS (Final)      |    152 bytes |      100 755 ops/s |           9 925 ns |\n| Swift macOS (JSON)       |    353 bytes |       18 534 ops/s |          53 953 ns |\n\n## Benchmark 2: Deserialization\nDeserialization benchmark C++ code:\n```c++\nBENCHMARK_FIXTURE(DeserializationFixture, \"Deserialize\")\n{\n    // Deserialize the account from the FBE stream\n    reader.deserialize(deserialized);\n}\n```\n\nDeserialization benchmark results:\n\n| Language \u0026 Platform      | Message size | Deserialization rate | Deserialization time |\n| :----------------------- | -----------: | -------------------: | -------------------: |\n| C++ Win64                |    252 bytes |      9 523 810 ops/s |               105 ns |\n| C++ Win64 (Final)        |    152 bytes |     10 989 011 ops/s |                91 ns |\n| C++ Win64 (JSON)         |    353 bytes |      1 375 516 ops/s |               727 ns |\n| C# Win64                 |    252 bytes |      1 014 199 ops/s |               986 ns |\n| C# Win64 (Final)         |    152 bytes |      1 607 717 ops/s |               622 ns |\n| C# Win64 (JSON)          |    341 bytes |        258 532 ops/s |             3 868 ns |\n| Go Win64                 |    252 bytes |      1 510 574 ops/s |               662 ns |\n| Go Win64 (Final)         |    152 bytes |      1 540 832 ops/s |               649 ns |\n| Go Win64 (JSON)          |    341 bytes |        251 825 ops/s |             3 971 ns |\n| Java Win64               |    252 bytes |      2 688 084 ops/s |               372 ns |\n| Java Win64 (Final)       |    152 bytes |      3 036 020 ops/s |               329 ns |\n| Java Win64 (JSON)        |    353 bytes |        308 675 ops/s |             3 240 ns |\n| JavaScript Win64         |    252 bytes |        133 892 ops/s |             7 469 ns |\n| JavaScript Win64 (Final) |    152 bytes |        292 273 ops/s |             3 422 ns |\n| JavaScript Win64 (JSON)  |    341 bytes |        289 417 ops/s |             3 455 ns |\n| Kotlin Win64             |    252 bytes |      2 280 923 ops/s |               438 ns |\n| Kotlin Win64 (Final)     |    152 bytes |      2 652 728 ops/s |               277 ns |\n| Kotlin Win64 (JSON)      |    353 bytes |        250 524 ops/s |             3 992 ns |\n| Python Win64             |    252 bytes |          8 305 ops/s |           120 411 ns |\n| Python Win64 (Final)     |    152 bytes |         11 661 ops/s |            85 758 ns |\n| Python Win64 (JSON)      |    324 bytes |         48 859 ops/s |            20 467 ns |\n| Ruby Win64               |    252 bytes |         24 351 ops/s |            41 066 ns |\n| Ruby Win64 (Final)       |    152 bytes |         33 555 ops/s |            29 802 ns |\n| Ruby Win64 (JSON)        |    353 bytes |         42 860 ops/s |            23 331 ns |\n| Swift macOS              |    252 bytes |         86 288 ops/s |            11 589 ns |\n| Swift macOS (Final)      |    152 bytes |        10 3519 ops/s |             9 660 ns |\n| Swift macOS (JSON)       |    353 bytes |         17 077 ops/s |            58 558 ns |\n\n## Benchmark 3: Verify\nVerify benchmark C++ code:\n```c++\nBENCHMARK_FIXTURE(VerifyFixture, \"Verify\")\n{\n    // Verify the account\n    model.verify();\n}\n```\n\nVerify benchmark results:\n\n| Language \u0026 Platform      | Message size |      Verify rate | Verify time |\n| :----------------------- | -----------: | ---------------: | ----------: |\n| C++ Win64                |    252 bytes | 31 250 000 ops/s |       32 ns |\n| C++ Win64 (Final)        |    152 bytes | 35 714 286 ops/s |       28 ns |\n| C# Win64                 |    252 bytes |  4 504 505 ops/s |      222 ns |\n| C# Win64 (Final)         |    152 bytes |  8 064 516 ops/s |      124 ns |\n| Go Win64                 |    252 bytes |  8 474 576 ops/s |      118 ns |\n| Go Win64 (Final)         |    152 bytes |  9 090 909 ops/s |      110 ns |\n| Java Win64               |    252 bytes | 11 790 374 ops/s |       85 ns |\n| Java Win64 (Final)       |    152 bytes | 16 205 533 ops/s |       62 ns |\n| JavaScript Win64         |    252 bytes |  1 105 627 ops/s |      905 ns |\n| JavaScript Win64 (Final) |    152 bytes |  5 700 408 ops/s |      175 ns |\n| Kotlin Win64             |    252 bytes |  8 625 935 ops/s |      116 ns |\n| Kotlin Win64 (Final)     |    152 bytes | 13 373 757 ops/s |       75 ns |\n| Python Win64             |    252 bytes |     20 825 ops/s |   48 019 ns |\n| Python Win64 (Final)     |    152 bytes |     23 590 ops/s |   42 391 ns |\n| Ruby Win64               |    252 bytes |     57 201 ops/s |   17 482 ns |\n| Ruby Win64 (Final)       |    152 bytes |     74 262 ops/s |   13 466 ns |\n| Swift macOS              |    252 bytes |    164 446 ops/s |    6 081 ns |\n| Swift macOS (Final)      |    152 bytes |    228 154 ops/s |    4 383 ns |\n","funding_links":[],"categories":["Serialization","C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchronoxor%2FFastBinaryEncoding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchronoxor%2FFastBinaryEncoding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchronoxor%2FFastBinaryEncoding/lists"}