Skip to content

Repository files navigation

dyproto

dyproto contains the implementation of a simple binary protocol that can be used to transfer data in the form of trivially copyable objects or containers thereof.

Primary Features

  • Type safety, because the reading and writing functions only accept objects that satisfy specific concepts
  • Error handling, because write functions return write results that may contain the number of bytes written or an error code
  • Customizability, because you can write your own types that satisfy the aforementioned specific concepts; moreover, you can read and write your own structural types so long as they're trivially copyable

Note that while write functions return write results, read functions return objects of type that you are trying to read and assert that the underlying buffer has enough space to read from.

Examples

The general prerequisite for all of the examples:

#include <dyproto/reader.hpp>
#include <dyproto/writer.hpp>

static constexpr std::size_t buffer_size = 1024;

std::array<std::byte, buffer_size> bytes{};

auto w = dyproto::writer{bytes};
auto r = dyproto::reader{bytes};

Reading and writing one object at a time:

w.write<std::int32_t>(64);
assert(r.read<std::int32_t> == 64);

w.write<std::uint8_t>(128);
w.write<std::vector<std::int64_t>>({-67, -65, 12, 42, -42, 91, 67});

assert(128 == r.read<std::uint8_t>());
assert(std::vector<std::int64_t>{-67, -65, 12, 42, -42, 91, 67}, r.read<std::vector<std::int64_t>>());

Reading and writing several objects at a time:

w.write<
	std::uint8_t,
	std::vector<std::int32_t>,
	std::int64_t,
>(
	255,
	{-1, 0, 1, 2, 3, 4},
	6767,
);

auto const [a, b, c] = r.read<
	std::uint8_t,
	std::vector<std::int32_t>,
	std::int64_t,
>();

assert(a == 255);
assert(b == std::vector<std::int32_t>{-1, 0, 1, 2, 3, 4});
assert(c == 6767);

Writing until we run out of space:

for (std::size_t i = 0; ; ++i)
{
	auto const result = w.write<std::size_t>(i);

	if (result)
	{
		continue;
	}

	auto const error_code = result.error();
	assert(error_code == std::errc::no_buffer_space);

	break;
}

Concepts

The protocol contains three library concepts that can be applied to various types:

  • dyproto::traits::argument models an argument, i.e. an object that can be read and written

  • dyproto::traits::trivial_argument models a trivial argument, i.e. a trivially copyable object

  • dyproto::traits::container_argument models a container argument, i.e. a container of trivial arguments

  • dyproto::traits::reservable_container_argument models a reservable container argument, i.e. a container argument that also has the reserve operation defined

A valid container argument container of type C is also required to:

  • define typename C::value_type - the type of contained objects

  • for a given rvalue object of the type convertible to the type of contained objects, ensure container.push_back(object) is a valid operation, e.g. by defining void C::push_back(typename C::value_type&&)

A valid reservable container argument container is required to:

  • ensure container.reserve(0uz) is a valid operation, e.g. by defining a member function void C::reserve(std::size_t)

The following STL containers satisfy the container argument requirements:

  • std::vector<T> for any T
  • std::list<T> for any T

Non-default allocators haven't been tested for but shouldn't be a problem in practice.

License

The library is licensed under either the MIT License or the Apache-2.0 License, at your option.

Authors

Artemy Astakhov (contact at aeverless dot dev)

About

A modern, lightweight binary protocol for exchanging data with easy serialization and deserialization of data structures

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages