Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ozancansel/rbs
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.
https://github.com/ozancansel/rbs
binary cpp17 raw serialization
Last synced: 22 days ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/ozancansel/rbs
- Owner: OzanCansel
- License: mit
- Created: 2022-09-03T08:44:21.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2023-04-02T15:39:49.000Z (almost 2 years ago)
- Last Synced: 2024-10-30T02:44:25.717Z (2 months ago)
- Topics: binary, cpp17, raw, serialization
- Language: C++
- Homepage:
- Size: 165 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# rbs
`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&` 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.- Header only library
- Usable with `find_package( rbs REQUIRED )` if it is installed to the system
- Needs C++17 or higher
- Only `Boost.Asio` and `Boost.Pfr` dependency## Examples
All examples use `helper.hpp` to print bytes. Here its content is :
``` C++
#pragma once#include
#include
#include
#include
#includeinline void print( std::string_view prefix , rbs::stream& ss )
{
std::cout << prefix << " | ";for ( auto it = buffers_begin( ss.buf().data() );
it != buffers_end( ss.buf().data() );
++it )
std::cout << std::setw( 2 )
<< std::setfill( '0' )
<< std::hex
<< std::uint32_t( std::uint8_t( *it ) )
<< ' ';std::cout << std::endl;
}
```### Primitives Serialization
`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.``` C++
#include
#include "helper.hpp"int main()
{
rbs::stream bes { rbs::endian::big };bes << char( 0x1F )
<< short( 0x0102 )
<< int( 0x01020304 )
<< float( 1234.56789f )
<< double( 123456789.123456789 );rbs::stream les { rbs::endian::little };
les << char( 0x1F )
<< short( 0x0102 )
<< int( 0x01020304 )
<< float( 1234.56789f )
<< double( 123456789.123456789 );rbs::stream nts { rbs::endian::native };
nts << char( 0x1F )
<< short( 0x0102 )
<< int( 0x01020304 )
<< float( 1234.56789f )
<< double( 123456789.123456789 );print( "big_endian " , bes );
print( "little_endian" , les );
print( "native " , nts );
}
```
Output :
```console
big_endian | 1f 01 02 01 02 03 04 44 9a 52 2c 41 9d 6f 34 54 7e 6b 75
little_endian | 1f 02 01 04 03 02 01 2c 52 9a 44 75 6b 7e 54 34 6f 9d 41
native | 1f 02 01 04 03 02 01 2c 52 9a 44 75 6b 7e 54 34 6f 9d 41
```### Struct Serialization
`rbs` provides a convenient mechanism to serialize/deserialize a struct by overlading `operator<<`, `operator>>` operators.``` C++
#include
#include
#include "helper.hpp"struct coordinate
{
float x;
float y;
float z;
};template
inline rbs::stream& operator<<( rbs::stream& ss , const coordinate& coord )
{
return ss << coord.x << coord.y << coord.z;
}int main()
{
rbs::stream bes { rbs::endian::big };
rbs::stream les { rbs::endian::little };coordinate coord { 1.0f , 2.0f , 3.0f };
bes << coord;
les << coord;print( "little -> coordinate" , bes );
print( "big -> coordinate" , les );
}
```
Output :
``` console
little -> coordinate | 3f 80 00 00 40 00 00 00 40 40 00 00
big -> coordinate | 00 00 80 3f 00 00 00 40 00 00 40 40
```### Aggregate Serialization
`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.``` C++
#include
#include
#include "helper.hpp"struct coordinate
{
float x;
float y;
float z;
};template<>
struct rbs::aggregate_serializable : std::true_type
{};int main()
{
rbs::stream bes { rbs::endian::big };
rbs::stream les { rbs::endian::little };coordinate coord { 1.0f , 2.0f , 3.0f };
bes << coord;
les << coord;print( "little -> coordinate" , bes );
print( "big -> coordinate" , les );
}
```
Output :
``` console
little -> coordinate | 3f 80 00 00 40 00 00 00 40 40 00 00
big -> coordinate | 00 00 80 3f 00 00 00 40 00 00 40 40
```### Scoped Enum Serialization
`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).``` C++
#include
#include "helper.hpp"enum class architecture : std::uint8_t
{
x86 = 10 ,
amd64
};enum class operating_system : std::uint16_t
{
gnu_linux = 20 ,
mac ,
win
};enum class byte_order
{
little = 30 ,
big
};struct computer
{
architecture arch;
operating_system sys;
byte_order endianness;
};template
inline rbs::stream& operator<<( rbs::stream& ss , const computer& comp )
{
return ss << comp.arch << comp.sys << comp.endianness;
}int main()
{
computer my_pc
{
architecture::amd64 ,
operating_system::gnu_linux ,
byte_order::little
};rbs::stream les { rbs::endian::little };
les << my_pc;
print( "computer -> little" , les );
}
```
Output :
```console
computer -> little | 0b 14 00 1e 00 00 00
```### File Output Example
`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.``` C++
#include
#includestruct coordinate
{
int x;
int y;
int z;
};template
rbs::stream& operator<<( rbs::stream& ss , const coordinate& coord )
{
return ss << coord.x << coord.y << coord.z;
}int main()
{
std::ofstream of { "coordinate.bin" };
rbs::stream out { of , rbs::endian::big };coordinate c { 1 , 2 , 3 };
out << c;
}
```
Output :
``` sh
# cat coordinate.bin | hexdump -C
00000000 00 00 00 01 00 00 00 02 00 00 00 03 |............|
```### Primitive Array Serialization
`rbs` provides built-in mechanism to serialize/deserialize an array which holds primitive types.``` C++
#include
#include
#include "helper.hpp"int main()
{
rbs::stream bes { rbs::endian::big };
rbs::stream les { rbs::endian::little };short numbers[] { 0x0102 , 0x0304 , 0x0506 , 0x0708 };
bes << numbers;
les << numbers;print( "little -> numbers" , bes );
print( "big -> numbers" , les );
}
```
Output :
``` console
little -> numbers | 01 02 03 04 05 06 07 08
big -> numbers | 02 01 04 03 06 05 08 07
```### User Defined Type Array Serialization
`rbs` provides built-in mechanism to serialize/deserialize an array which holds user defined types.``` C++
#include
#include
#include "helper.hpp"struct foo
{
short x;
short y;
};template<>
struct rbs::aggregate_serializable : std::true_type
{};int main()
{
rbs::stream bes { rbs::endian::big };
rbs::stream les { rbs::endian::little };foo foos[]
{
{ 0x01 , 0x02 } ,
{ 0x03 , 0x04 } ,
{ 0x05 , 0x06 } ,
{ 0x07 , 0x08 }
};bes << foos;
les << foos;print( "little -> foos" , bes );
print( "big -> foos" , les );
}
```
Output :
``` console
little -> foos | 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08
big -> foos | 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00
```### Serialize Util Function
`rbs` provides `serialize_be`, `serialize_le`, `serialize_nt` functions for less verbose code snippets.``` C++
#include
#include
#include "helper.hpp"int main()
{
boost::asio::streambuf buffer;rbs::serialize_be( 0x01020304 , buffer );
rbs::serialize_le( 0x01020304 , buffer );
rbs::serialize_nt( 0x01020304 , buffer );print( "beint|leint|ntint" , buffer );
}
```
Output :
``` console
beint|leint|ntint | 01 02 03 04 04 03 02 01 04 03 02 01
```## How to use ?
### Option 1. Install to the system
- Install `rbs` as system-wide.
```bash
cd $(mktemp -d)
git clone https://github.com/OzanCansel/rbs.git
cd rbs
mkdir build && cd build
cmake ..
sudo cmake --build . --target install -- -j$(nproc)
```#### Option 1.1.
- Include `rbs` to your cmake project with `find_package( rbs )`
``` cmake
cmake_minimum_required( VERSION 3.10 )
project( my_project )# Allows you to use rbs
find_package( rbs REQUIRED )add_executable( my_binary main.cpp )
target_link_libraries( my_binary PRIVATE rbs::rbs )
```#### Option 1.2.
- 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.### Option 2. Add as a subdirectory
- Add as an subdirectory to your existing cmake project.```bash
cd already_existing_project
git clone https://github.com/OzanCansel/rbs.git
```
``` cmake
cmake_minimum_required( VERSION 3.10 )
project( already_existing_project )# Allows you to use rbs
add_subdirectory( rbs EXCLUDE_FROM_ALL )add_executable( my_binary main.cpp )
target_link_libraries( my_binary PRIVATE rbs::rbs )
```# LICENSE
[MIT](https://raw.githubusercontent.com/OzanCansel/rbs/master/LICENSE)