{"id":18008437,"url":"https://github.com/ozancansel/rbs","last_synced_at":"2025-08-23T02:05:17.063Z","repository":{"id":123805091,"uuid":"532204514","full_name":"OzanCansel/rbs","owner":"OzanCansel","description":"Binary serialization library which doesn't append, prepend or insert any additional bytes other than original footprint of the types. It is also endian-aware.","archived":false,"fork":false,"pushed_at":"2023-04-02T15:39:49.000Z","size":169,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-09T21:43:36.197Z","etag":null,"topics":["binary","cpp17","raw","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/OzanCansel.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":"2022-09-03T08:44:21.000Z","updated_at":"2022-09-07T20:12:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"41784166-b82f-4253-a07c-cc2f18d90a61","html_url":"https://github.com/OzanCansel/rbs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OzanCansel%2Frbs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OzanCansel%2Frbs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OzanCansel%2Frbs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OzanCansel%2Frbs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OzanCansel","download_url":"https://codeload.github.com/OzanCansel/rbs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247174402,"owners_count":20896074,"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","cpp17","raw","serialization"],"created_at":"2024-10-30T01:18:44.127Z","updated_at":"2025-04-04T11:47:20.657Z","avatar_url":"https://github.com/OzanCansel.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rbs\n`rbs` is raw binary serialization library. It doesn't append, prepend or insert any additional bytes. It just serializes/deserializes memory footprint of the types to/from `std::streambuf\u0026` which you provide by its constructors. If nothing is provided it instantiates a standalone `boost::asio::streambuf` buffer and uses it. It is also __endian-aware__ so it can provide portability across different platforms.\n\n- Header only library\n- Usable with `find_package( rbs REQUIRED )` if it is installed to the system\n- Needs C++17 or higher\n- Only `Boost.Asio` and `Boost.Pfr` dependency\n\n## Examples\nAll examples use `helper.hpp` to print bytes. Here its content is :\n``` C++\n#pragma once\n\n#include \u003ciostream\u003e\n#include \u003ciomanip\u003e\n#include \u003cstring_view\u003e\n#include \u003cboost/asio/buffers_iterator.hpp\u003e\n#include \u003crbs/stream.hpp\u003e\n\ninline void print( std::string_view prefix , rbs::stream\u003ctrue\u003e\u0026 ss )\n{\n    std::cout \u003c\u003c prefix \u003c\u003c \" | \";\n\n    for ( auto it  = buffers_begin( ss.buf().data() );\n               it != buffers_end( ss.buf().data() );\n               ++it )\n        std::cout \u003c\u003c std::setw( 2 )\n                  \u003c\u003c std::setfill( '0' )\n                  \u003c\u003c std::hex\n                  \u003c\u003c std::uint32_t( std::uint8_t( *it ) )\n                  \u003c\u003c ' ';\n\n    std::cout \u003c\u003c std::endl;\n}\n```\n\n### Primitives Serialization\n`rbs` is able to serialize [arithmetic types](https://en.cppreference.com/w/cpp/types/is_arithmetic) in regards to [byte order](https://en.cppreference.com/w/cpp/types/endian) of the `stream` class.\n\n``` C++\n#include \u003crbs/stream.hpp\u003e\n#include \"helper.hpp\"\n\nint main()\n{\n    rbs::stream bes { rbs::endian::big };\n\n    bes \u003c\u003c char( 0x1F )\n        \u003c\u003c short( 0x0102 )\n        \u003c\u003c int( 0x01020304 )\n        \u003c\u003c float( 1234.56789f )\n        \u003c\u003c double( 123456789.123456789 );\n\n    rbs::stream les { rbs::endian::little };\n\n    les \u003c\u003c char( 0x1F )\n        \u003c\u003c short( 0x0102 )\n        \u003c\u003c int( 0x01020304 )\n        \u003c\u003c float( 1234.56789f )\n        \u003c\u003c double( 123456789.123456789 );\n\n    rbs::stream nts { rbs::endian::native };\n\n    nts \u003c\u003c char( 0x1F )\n        \u003c\u003c short( 0x0102 )\n        \u003c\u003c int( 0x01020304 )\n        \u003c\u003c float( 1234.56789f )\n        \u003c\u003c double( 123456789.123456789 );\n\n    print( \"big_endian   \" , bes );\n    print( \"little_endian\" , les );\n    print( \"native       \" , nts );\n}\n```\nOutput :\n```console\nbig_endian    | 1f 01 02 01 02 03 04 44 9a 52 2c 41 9d 6f 34 54 7e 6b 75 \nlittle_endian | 1f 02 01 04 03 02 01 2c 52 9a 44 75 6b 7e 54 34 6f 9d 41 \nnative        | 1f 02 01 04 03 02 01 2c 52 9a 44 75 6b 7e 54 34 6f 9d 41\n```\n\n### Struct Serialization\n`rbs` provides a convenient mechanism to serialize/deserialize a struct by overlading `operator\u003c\u003c`, `operator\u003e\u003e` operators.\n\n``` C++\n#include \u003ciostream\u003e\n#include \u003crbs/stream.hpp\u003e\n#include \"helper.hpp\"\n\nstruct coordinate\n{\n    float x;\n    float y;\n    float z;\n};\n\ntemplate\u003cauto... Args\u003e\ninline rbs::stream\u003cArgs...\u003e\u0026 operator\u003c\u003c( rbs::stream\u003cArgs...\u003e\u0026 ss , const coordinate\u0026 coord )\n{\n    return ss \u003c\u003c coord.x \u003c\u003c coord.y \u003c\u003c coord.z;\n}\n\nint main()\n{\n    rbs::stream bes { rbs::endian::big    };\n    rbs::stream les { rbs::endian::little };\n\n    coordinate coord { 1.0f , 2.0f , 3.0f };\n\n    bes \u003c\u003c coord;\n    les \u003c\u003c coord;\n\n    print( \"little -\u003e coordinate\" , bes );\n    print( \"big    -\u003e coordinate\" , les );\n}\n```\nOutput :\n``` console\nlittle -\u003e coordinate | 3f 80 00 00 40 00 00 00 40 40 00 00\nbig    -\u003e coordinate | 00 00 80 3f 00 00 00 40 00 00 40 40\n```\n\n### Aggregate Serialization\n`rbs` provides a convenient mechanism to serialize/deserialize an aggregate type automatically. Member of aggregate types will be serialized/deserialized in order they are declared.\n\n``` C++\n#include \u003ciostream\u003e\n#include \u003crbs/rbs.hpp\u003e\n#include \"helper.hpp\"\n\nstruct coordinate\n{\n    float x;\n    float y;\n    float z;\n};\n\ntemplate\u003c\u003e\nstruct rbs::aggregate_serializable\u003ccoordinate\u003e : std::true_type\n{};\n\nint main()\n{\n    rbs::stream bes { rbs::endian::big    };\n    rbs::stream les { rbs::endian::little };\n\n    coordinate coord { 1.0f , 2.0f , 3.0f };\n\n    bes \u003c\u003c coord;\n    les \u003c\u003c coord;\n\n    print( \"little -\u003e coordinate\" , bes );\n    print( \"big    -\u003e coordinate\" , les );\n}\n```\nOutput :\n``` console\nlittle -\u003e coordinate | 3f 80 00 00 40 00 00 00 40 40 00 00 \nbig    -\u003e coordinate | 00 00 80 3f 00 00 00 40 00 00 40 40\n```\n\n### Scoped Enum Serialization\n`rbs` is able to serialize [scoped enums](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) in regards to its [underlying_type](https://en.cppreference.com/w/cpp/types/underlying_type).\n\n``` C++\n#include \u003crbs/stream.hpp\u003e\n#include \"helper.hpp\"\n\nenum class architecture : std::uint8_t\n{\n    x86   = 10 ,\n    amd64\n};\n\nenum class operating_system : std::uint16_t\n{\n    gnu_linux = 20 ,\n    mac ,\n    win\n};\n\nenum class byte_order\n{\n    little = 30 ,\n    big\n};\n\nstruct computer\n{\n    architecture     arch;\n    operating_system sys;\n    byte_order       endianness;\n};\n\ntemplate\u003cauto... Args\u003e\ninline rbs::stream\u003cArgs...\u003e\u0026 operator\u003c\u003c( rbs::stream\u003cArgs...\u003e\u0026 ss , const computer\u0026 comp )\n{\n    return ss \u003c\u003c comp.arch \u003c\u003c comp.sys \u003c\u003c comp.endianness;\n}\n\nint main()\n{\n    computer my_pc\n    {\n        architecture::amd64 ,\n        operating_system::gnu_linux ,\n        byte_order::little\n    };\n\n    rbs::stream les { rbs::endian::little };\n\n    les \u003c\u003c my_pc;\n\n    print( \"computer -\u003e little\" , les );\n}\n```\nOutput :\n```console\ncomputer -\u003e little | 0b 14 00 1e 00 00 00 \n```\n\n### File Output Example\n`rbs` is able to work with standard streams such as [std::ofstream](https://en.cppreference.com/w/cpp/io/basic_ofstream). This example writes serialized `coordinate` object to the `coordinate.bin` file.\n\n``` C++\n#include \u003cfstream\u003e\n#include \u003crbs/stream.hpp\u003e\n\nstruct coordinate\n{\n    int x;\n    int y;\n    int z;\n};\n\ntemplate\u003cauto... Args\u003e\nrbs::stream\u003cArgs...\u003e\u0026 operator\u003c\u003c( rbs::stream\u003cArgs...\u003e\u0026 ss , const coordinate\u0026 coord )\n{\n    return ss \u003c\u003c coord.x \u003c\u003c coord.y \u003c\u003c coord.z;\n}\n\nint main()\n{\n    std::ofstream  of  { \"coordinate.bin\" };\n    rbs::stream out { of , rbs::endian::big };\n\n    coordinate c { 1 , 2 , 3 };\n\n    out \u003c\u003c c;\n}\n```\nOutput :\n``` sh\n# cat coordinate.bin | hexdump -C\n00000000  00 00 00 01 00 00 00 02  00 00 00 03              |............|\n```\n\n### Primitive Array Serialization\n`rbs` provides built-in mechanism to serialize/deserialize an array which holds primitive types.\n\n``` C++\n#include \u003ciostream\u003e\n#include \u003crbs/rbs.hpp\u003e\n#include \"helper.hpp\"\n\nint main()\n{\n    rbs::stream bes { rbs::endian::big    };\n    rbs::stream les { rbs::endian::little };\n\n    short numbers[] { 0x0102 , 0x0304 , 0x0506 , 0x0708 };\n\n    bes \u003c\u003c numbers;\n    les \u003c\u003c numbers;\n\n    print( \"little -\u003e numbers\" , bes );\n    print( \"big    -\u003e numbers\" , les );\n}\n```\nOutput :\n``` console\nlittle -\u003e numbers | 01 02 03 04 05 06 07 08 \nbig    -\u003e numbers | 02 01 04 03 06 05 08 07\n```\n\n### User Defined Type Array Serialization\n`rbs` provides built-in mechanism to serialize/deserialize an array which holds user defined types.\n\n``` C++\n#include \u003ciostream\u003e\n#include \u003crbs/rbs.hpp\u003e\n#include \"helper.hpp\"\n\nstruct foo\n{\n    short x;\n    short y;\n};\n\ntemplate\u003c\u003e\nstruct rbs::aggregate_serializable\u003cfoo\u003e : std::true_type\n{};\n\nint main()\n{\n    rbs::stream bes { rbs::endian::big    };\n    rbs::stream les { rbs::endian::little };\n\n    foo foos[]\n    {\n        { 0x01 , 0x02 } ,\n        { 0x03 , 0x04 } ,\n        { 0x05 , 0x06 } ,\n        { 0x07 , 0x08 }\n    };\n\n    bes \u003c\u003c foos;\n    les \u003c\u003c foos;\n\n    print( \"little -\u003e foos\" , bes );\n    print( \"big    -\u003e foos\" , les );\n}\n```\nOutput :\n``` console\nlittle -\u003e foos | 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08\nbig    -\u003e foos | 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00\n```\n\n### Serialize Util Function\n`rbs` provides `serialize_be`, `serialize_le`, `serialize_nt` functions for less verbose code snippets.\n\n``` C++\n#include \u003ciostream\u003e\n#include \u003crbs/serialize_util.hpp\u003e\n#include \"helper.hpp\"\n\nint main()\n{\n    boost::asio::streambuf buffer;\n\n    rbs::serialize_be( 0x01020304 , buffer );\n    rbs::serialize_le( 0x01020304 , buffer );\n    rbs::serialize_nt( 0x01020304 , buffer );\n\n    print( \"beint|leint|ntint\" , buffer );\n}\n```\nOutput :\n``` console\nbeint|leint|ntint | 01 02 03 04 04 03 02 01 04 03 02 01\n```\n\n## How to use ?\n### Option 1. Install to the system\n- Install `rbs` as system-wide.\n```bash\ncd $(mktemp -d)\ngit clone https://github.com/OzanCansel/rbs.git\ncd rbs\nmkdir build \u0026\u0026 cd build\ncmake ..\nsudo cmake --build . --target install -- -j$(nproc)\n```\n\n#### Option 1.1.\n- Include `rbs` to your cmake project with `find_package( rbs )`\n``` cmake\ncmake_minimum_required( VERSION 3.10 )\nproject( my_project )\n\n# Allows you to use rbs\nfind_package( rbs REQUIRED )\n\nadd_executable( my_binary main.cpp )\n\ntarget_link_libraries( my_binary PRIVATE rbs::rbs )\n```\n\n#### Option 1.2.\n- It is not obliged to be included by a cmake project. `rbs` is header only so it will be visible after it is installed to the system. So just include it and make sure that you enabled C++17 standard.\n\n### Option 2. Add as a subdirectory\n- Add as an subdirectory to your existing cmake project.\n\n```bash\ncd already_existing_project\ngit clone https://github.com/OzanCansel/rbs.git\n```\n``` cmake\ncmake_minimum_required( VERSION 3.10 )\nproject( already_existing_project )\n\n# Allows you to use rbs\nadd_subdirectory( rbs EXCLUDE_FROM_ALL )\n\nadd_executable( my_binary main.cpp )\n\ntarget_link_libraries( my_binary PRIVATE rbs::rbs )\n```\n\n# LICENSE\n[MIT](https://raw.githubusercontent.com/OzanCansel/rbs/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fozancansel%2Frbs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fozancansel%2Frbs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fozancansel%2Frbs/lists"}