emlabcpp
modern opinionated embedded C++ library
emlabcpp::protocol Namespace Reference

MIT License. More...

Namespaces

 detail
 

Classes

class  multiplexed_endpoint
 
struct  conversion_result
 
struct  endianess_wrapper
 Follows a set of special data types used for definition of protocol. More...
 
struct  group
 Serializes values from definitions Ds to std::variant. More...
 
struct  tag_group
 
struct  sized_buffer
 Creates a segment starting with counter defined by CounterDef, this counter limits how many bytes are passed to deserialization process, bytes after the limit ale not considered by this segment. More...
 
struct  value_offset
 The value defined by D present in the message is offseted by Offset. More...
 
struct  converter_def_type_base
 More complex constructs have custom mechanics that internally produces def_type alias used by the library to serialize/deserialize it. More...
 
struct  command
 Command group represents a segment in the message, that may contain multiple different variants of value, that are identified by ID at the beginning of the segment. More...
 
struct  command_group
 Command group should be used as a collection of commands that are selected based on the ID, during the deserialization first command that matches is selected. More...
 
struct  command_group< Endianess >
 
struct  converter
 converter<T,E> structure defines how type T should be serialized and deserialized. More...
 
struct  backup_converter
 
struct  converter< D, Endianess >
 
struct  converter< std::array< D, N >, Endianess >
 
struct  converter< std::tuple< Ds... >, Endianess >
 
struct  converter< std::variant< Ds... >, Endianess >
 
struct  converter< std::monostate, Endianess >
 
struct  converter< std::optional< T >, Endianess >
 
struct  converter< std::bitset< N >, Endianess >
 
struct  converter< message< N >, Endianess >
 
struct  converter< sizeless_message< N >, Endianess >
 
struct  converter< value_offset< D, Offset >, Endianess >
 
struct  converter< bounded< D, Min, Max >, Endianess >
 
struct  converter< sized_buffer< CounterDef, D >, Endianess >
 
struct  converter< tag< V >, Endianess >
 
struct  converter< tag_group< Ds... >, Endianess >
 
struct  converter< group< Ds... >, Endianess >
 
struct  converter< endianess_wrapper< Endianess, D >, ParentEndianess >
 
struct  converter< string_buffer< N >, Endianess >
 
struct  converter< std::chrono::duration< Rep, Ratio >, Endianess >
 
struct  converter< error_record, Endianess >
 
struct  converter< static_vector< T, N >, Endianess >
 
struct  backup_converter< T, Endianess >
 
struct  memcpy_converter
 
struct  endpoint_load_error
 
class  endpoint
 
struct  error_record
 
struct  handler
 handler< T > should be used to execute actual serialization and deserealization of protocol definition. More...
 
class  message
 Protocol library has custom type that represents message, however this is just simple overaly over std::array that remembers how many bytes are used. More...
 
class  sizeless_message
 Sizeless message is class that behaves in a same way as normal message, however it is serialized differently. More...
 
struct  packet
 
struct  packet_handler
 
struct  register_handler
 Handler for serialization and extraction of datatypes used by the register_map. More...
 
struct  register_pair
 Structure that represents definition of one register in the map. More...
 
class  register_map
 Register map is abstraction to work with registers of external devices. More...
 
struct  sequencer_read_request
 
class  sequencer
 
struct  serializer
 
struct  serializer< float, Endianess >
 
struct  serializer< bool, Endianess >
 
struct  msg_format
 
struct  proto_traits
 Each definition of item provided to protocol library should have specialization of 'proto_traits' structure. More...
 
struct  backup_proto_traits
 
struct  proto_traits< D >
 
struct  proto_traits< std::array< D, N > >
 
struct  proto_traits< std::tuple< Ds... > >
 
struct  proto_traits< std::variant< Ds... > >
 
struct  proto_traits< std::monostate >
 
struct  proto_traits< std::bitset< N > >
 
struct  proto_traits< sizeless_message< N > >
 
struct  proto_traits< message< N > >
 
struct  proto_traits< value_offset< D, Offset > >
 
struct  proto_traits< bounded< D, Min, Max > >
 
struct  proto_traits< sized_buffer< CounterType, D > >
 
struct  proto_traits< tag< V > >
 
struct  proto_traits< group< Ds... > >
 
struct  proto_traits< tag_group< Ds... > >
 
struct  proto_traits< endianess_wrapper< Endianess, D > >
 
struct  proto_traits< string_buffer< N > >
 
struct  proto_traits< std::chrono::duration< Rep, Ratio > >
 
struct  proto_traits< error_record >
 
struct  proto_traits< static_vector< T, N > >
 
struct  proto_traits< std::optional< T > >
 
struct  backup_proto_traits< T >
 
struct  tuple
 tuple is high levle alternative to use just 'std::tuple' that is more friendly for standalone protocols. More...
 

Typedefs

using channel_type = uint16_t
 
using multiplexer_channel_handler = handler< channel_type, std::endian::little >
 
template<std::size_t N>
using multiplexer_payload = tuple< std::endian::little, channel_type, sizeless_message< N > >
 
template<std::size_t N>
using multiplexer_value = typename multiplexer_payload< N >::value_type
 
template<std::size_t N>
using multiplexer_message = typename multiplexer_payload< N >::message_type
 
template<std::size_t N>
using multiplexer_handler = handler< multiplexer_payload< N > >
 
using multiplexer_service_protocol = std::tuple< multiplexer_enum >
 
using multiplexer_service_msg = typename handler< multiplexer_service_protocol >::message_type
 
template<typename D , std::endian E>
using converter_for = decltype(converter_for_impl< D, E >())
 
using endpoint_error = std::variant< error_record, endpoint_load_error >
 
using mark = string_buffer< mark_size >
 
template<typename Def , typename Payload >
using packet_base = tuple< Def::endianess, std::decay_t< decltype(Def::prefix) >, sized_buffer< typename Def::size_type, Payload >, typename Def::checksum_type >
 
using userializer = serializer< utype, Endianess >
 
using size_type = bounded< std::size_t, max_size, max_size >
 
template<typename D >
using traits_for = decltype(traits_for_impl< D >())
 

Enumerations

enum  multiplexer_enum : uint8_t {
  PORT_MATCH_ERROR = 0 ,
  PROTOCOL_ERROR = 1
}
 

Functions

std::tuple< bool, std::span< std::byte > > serialize_multiplexed (channel_type channel, std::span< std::byte const > data, std::span< std::byte > target)
 
template<std::size_t N>
multiplexer_message< Nserialize_multiplexed (channel_type channel, message< N > const &m)
 
template<typename BinaryCallable >
outcome extract_multiplexed (std::span< std::byte const > const &msg, BinaryCallable handle_cb)
 
template<slot... Slotted>
outcome multiplexed_dispatch (channel_type chann, auto const &data, Slotted &... slotted)
 
template<typename D , std::endian E>
auto converter_for_impl ()
 
template<typename D , std::endian E, typename T >
std::size_t serialize_range (std::span< std::byte > const buffer, view< T const * > const &data)
 
template<typename D , std::endian E, typename T >
conversion_result deserialize_range (std::span< std::byte const > const &buffer, view< T * > const &data)
 
template<std::convertible_to< uint8_t >... Ts>
 message (Ts... inpt) -> message< sizeof...(Ts) >
 
template<std::convertible_to< uint8_t >... Ts>
 sizeless_message (Ts... inpt) -> sizeless_message< sizeof...(Ts) >
 
template<typename Map , typename UnaryCallable >
void for_each_register (Map const &m, UnaryCallable &&f)
 
template<typename Sequencer , typename ReadCallback >
std::optional< typename Sequencer::message_type > sequencer_simple_load (std::size_t const read_limit, ReadCallback &&read)
 
template<base_type T, std::endian Endianess>
 requires (std::is_enum_v< T >) struct serializer< T
 
static constexpr void serialize_at (std::span< std::byte, max_size > buffer, T item)
 
static constexpr T deserialize (std::span< std::byte const, max_size > const &buffer)
 
template<typename T >
static void pretty_print_msg_format (auto &&w, msg_format< T > wrapper)
 
template<typename D >
consteval auto traits_for_impl ()
 

Variables

static constexpr channel_type multiplexer_service_id = 0
 
template<typename T >
concept slot
 
template<typename T >
concept base_type = std::is_floating_point_v< T > || std::is_integral_v< T > || std::is_enum_v< T >
 Concept that matches types considered base - serialized directly by using byte shifting. More...
 
template<typename T >
concept converter_check
 converter_check<T> concept verifies that 'T' is valid overload of converter. More...
 
static constexpr std::size_t mark_size = 16
 
static constexpr auto SIZE_ERR = mark( "EMCPPSIZE" )
 
static constexpr auto LOWSIZE_ERR = mark( "EMCPPLOWSIZE" )
 not enough bytes left in the message for the item More...
 
static constexpr auto BIGSIZE_ERR = mark( "EMCPPBIGSIZE" )
 too much bytes left in the message for the item More...
 
static constexpr auto BOUNDS_ERR = mark( "EMCPPBOUNDS" )
 value in the message is outside of the range of bounded type More...
 
static constexpr auto UNDEFVAR_ERR = mark( "EMCPPUNDEFVAR" )
 variant id is outside of the range for defined variant More...
 
static constexpr auto BADVAL_ERR = mark( "EMCPPBADVAL" )
 parsed value is not correct, such as constant More...
 
static constexpr auto GROUP_ERR = mark( "EMCPPGRPMTCH" )
 no item of group matched the content of message More...
 
static constexpr auto CHECKSUM_ERR = mark( "EMCPPCHECKSM" )
 wrong checksum in the protocol More...
 
template<typename T >
concept message_derived = requires( T val ) { detail::message_derived_test( val ); }
 concept matches any type that is message or derives from it. More...
 
template<typename T >
concept packet_def
 
template<typename UnaryCallable , typename Registers >
concept register_map_void_returning
 
 Endianess
 
static constexpr std::size_t max_size = userializer::max_size
 
template<typename D >
concept convertible
 This concepts limits types to types that can be declared, that is the overload of 'traits_for' is fully defined: traits_for::value_type contains definition of value produced by the declaration, traits_for::max_size contains estimated maximal size in bytes taken by the serialized value in the message. More...
 
template<typename T >
concept fixedly_sized = traits_for< T >::min_size == traits_for< T >::max_size
 

Detailed Description

MIT License.

Copyright (c) 2025 Jan Veverak Koniarik

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Class Documentation

◆ emlabcpp::protocol::group

struct emlabcpp::protocol::group

template<typename... Ds>
struct emlabcpp::protocol::group< Ds >

Serializes values from definitions Ds to std::variant.

The byte message does not contain identificator of variant used, rather the first definition that manages to deserialize the message is used.

Class Members
def_type

◆ emlabcpp::protocol::tag_group

struct emlabcpp::protocol::tag_group

template<typename... Ds>
struct emlabcpp::protocol::tag_group< Ds >

Class Members
def_type

◆ emlabcpp::protocol::sized_buffer

struct emlabcpp::protocol::sized_buffer

template<typename CounterDef, typename D>
struct emlabcpp::protocol::sized_buffer< CounterDef, D >

Creates a segment starting with counter defined by CounterDef, this counter limits how many bytes are passed to deserialization process, bytes after the limit ale not considered by this segment.

Class Members
typedef CounterDef counter_type
typedef D def_type

◆ emlabcpp::protocol::command_group< Endianess >

struct emlabcpp::protocol::command_group< Endianess >

template<std::endian Endianess>
struct emlabcpp::protocol::command_group< Endianess >

Class Members
with_commands

◆ emlabcpp::protocol::converter

struct emlabcpp::protocol::converter

template<typename, std::endian>
struct emlabcpp::protocol::converter< typename, endian >

converter<T,E> structure defines how type T should be serialized and deserialized.

Each type or kind of types should overlead this structure and use same attributes as traits_for<T>. E is edianess of the serialization used.

◆ emlabcpp::protocol::backup_converter

struct emlabcpp::protocol::backup_converter

template<typename, std::endian>
struct emlabcpp::protocol::backup_converter< typename, endian >

◆ emlabcpp::protocol::endpoint_load_error

struct emlabcpp::protocol::endpoint_load_error

◆ emlabcpp::protocol::error_record

struct emlabcpp::protocol::error_record
+ Collaboration diagram for emlabcpp::protocol::error_record:
Class Members
mark error_mark
size_t offset

◆ emlabcpp::protocol::msg_format

struct emlabcpp::protocol::msg_format

template<typename T>
struct emlabcpp::protocol::msg_format< T >

+ Collaboration diagram for emlabcpp::protocol::msg_format< T >:
Class Members
T item

◆ emlabcpp::protocol::proto_traits

struct emlabcpp::protocol::proto_traits

template<typename D>
struct emlabcpp::protocol::proto_traits< D >

Each definition of item provided to protocol library should have specialization of 'proto_traits' structure.

This contains basic information of how it should be serialized.

◆ emlabcpp::protocol::backup_proto_traits

struct emlabcpp::protocol::backup_proto_traits

template<typename D>
struct emlabcpp::protocol::backup_proto_traits< D >

Typedef Documentation

◆ channel_type

using emlabcpp::protocol::channel_type = typedef uint16_t

◆ converter_for

template<typename D , std::endian E>
using emlabcpp::protocol::converter_for = typedef decltype( converter_for_impl< D, E >() )

◆ endpoint_error

◆ mark

◆ multiplexer_channel_handler

using emlabcpp::protocol::multiplexer_channel_handler = typedef handler< channel_type, std::endian::little >

◆ multiplexer_handler

template<std::size_t N>
using emlabcpp::protocol::multiplexer_handler = typedef handler< multiplexer_payload< N > >

◆ multiplexer_message

template<std::size_t N>
using emlabcpp::protocol::multiplexer_message = typedef typename multiplexer_payload< N >::message_type

◆ multiplexer_payload

template<std::size_t N>
using emlabcpp::protocol::multiplexer_payload = typedef tuple< std::endian::little, channel_type, sizeless_message< N > >

◆ multiplexer_service_msg

◆ multiplexer_service_protocol

◆ multiplexer_value

template<std::size_t N>
using emlabcpp::protocol::multiplexer_value = typedef typename multiplexer_payload< N >::value_type

◆ packet_base

template<typename Def , typename Payload >
using emlabcpp::protocol::packet_base = typedef tuple< Def::endianess, std::decay_t< decltype( Def::prefix ) >, sized_buffer< typename Def::size_type, Payload >, typename Def::checksum_type >

◆ size_type

using emlabcpp::protocol::size_type = typedef bounded< std::size_t, max_size, max_size >

◆ traits_for

template<typename D >
using emlabcpp::protocol::traits_for = typedef decltype( traits_for_impl< D >() )

◆ userializer

Enumeration Type Documentation

◆ multiplexer_enum

Enumerator
PORT_MATCH_ERROR 
PROTOCOL_ERROR 

Function Documentation

◆ converter_for_impl()

template<typename D , std::endian E>
auto emlabcpp::protocol::converter_for_impl ( )

◆ deserialize()

static constexpr T emlabcpp::protocol::deserialize ( std::span< std::byte const, max_size > const &  buffer)
staticconstexpr

◆ deserialize_range()

template<typename D , std::endian E, typename T >
conversion_result emlabcpp::protocol::deserialize_range ( std::span< std::byte const > const &  buffer,
view< T * > const &  data 
)

◆ extract_multiplexed()

template<typename BinaryCallable >
outcome emlabcpp::protocol::extract_multiplexed ( std::span< std::byte const > const &  msg,
BinaryCallable  handle_cb 
)

References deserialize(), and max_size.

◆ for_each_register()

template<typename Map , typename UnaryCallable >
void emlabcpp::protocol::for_each_register ( Map const &  m,
UnaryCallable &&  f 
)

References emlabcpp::f.

◆ message()

template<std::convertible_to< uint8_t >... Ts>
emlabcpp::protocol::message ( Ts...  inpt) -> message< sizeof...(Ts) >

◆ multiplexed_dispatch()

template<slot... Slotted>
outcome emlabcpp::protocol::multiplexed_dispatch ( channel_type  chann,
auto const &  data,
Slotted &...  slotted 
)

◆ pretty_print_msg_format()

template<typename T >
static void emlabcpp::protocol::pretty_print_msg_format ( auto &&  w,
msg_format< T >  wrapper 
)
static

◆ requires()

template<base_type T, std::endian Endianess>
emlabcpp::protocol::requires ( std::is_enum_v< T >  )

◆ sequencer_simple_load()

template<typename Sequencer , typename ReadCallback >
std::optional< typename Sequencer::message_type > emlabcpp::protocol::sequencer_simple_load ( std::size_t const  read_limit,
ReadCallback &&  read 
)

◆ serialize_at()

static constexpr void emlabcpp::protocol::serialize_at ( std::span< std::byte, max_size buffer,
item 
)
staticconstexpr

◆ serialize_multiplexed() [1/2]

template<std::size_t N>
multiplexer_message< N > emlabcpp::protocol::serialize_multiplexed ( channel_type  channel,
message< N > const &  m 
)

◆ serialize_multiplexed() [2/2]

std::tuple< bool, std::span< std::byte > > emlabcpp::protocol::serialize_multiplexed ( channel_type  channel,
std::span< std::byte const >  data,
std::span< std::byte >  target 
)
inline

◆ serialize_range()

template<typename D , std::endian E, typename T >
std::size_t emlabcpp::protocol::serialize_range ( std::span< std::byte > const  buffer,
view< T const * > const &  data 
)

◆ sizeless_message()

template<std::convertible_to< uint8_t >... Ts>
emlabcpp::protocol::sizeless_message ( Ts...  inpt) -> sizeless_message< sizeof...(Ts) >

◆ traits_for_impl()

template<typename D >
consteval auto emlabcpp::protocol::traits_for_impl ( )

Variable Documentation

◆ BADVAL_ERR

constexpr auto emlabcpp::protocol::BADVAL_ERR = mark( "EMCPPBADVAL" )
staticconstexpr

parsed value is not correct, such as constant

◆ base_type

template<typename T >
concept emlabcpp::protocol::base_type = std::is_floating_point_v< T > || std::is_integral_v< T > || std::is_enum_v< T >

Concept that matches types considered base - serialized directly by using byte shifting.

◆ BIGSIZE_ERR

constexpr auto emlabcpp::protocol::BIGSIZE_ERR = mark( "EMCPPBIGSIZE" )
staticconstexpr

too much bytes left in the message for the item

◆ BOUNDS_ERR

constexpr auto emlabcpp::protocol::BOUNDS_ERR = mark( "EMCPPBOUNDS" )
staticconstexpr

value in the message is outside of the range of bounded type

◆ CHECKSUM_ERR

constexpr auto emlabcpp::protocol::CHECKSUM_ERR = mark( "EMCPPCHECKSM" )
staticconstexpr

wrong checksum in the protocol

◆ converter_check

template<typename T >
concept emlabcpp::protocol::converter_check
Initial value:
= requires() {
{ T::max_size } -> std::convertible_to< std::size_t >;
typename T::value_type;
requires bounded_derived< typename T::size_type >;
} && requires( std::span< std::byte, T::max_size > buff, typename T::value_type item ) {
{ T::serialize_at( buff, item ) } -> std::same_as< typename T::size_type >;
} && requires( std::span< std::byte const > buff, typename T::value_type item ) {
T::deserialize( buff, item );
}
requires(!range_container< Container >) std
Definition: impl.h:81
static constexpr T deserialize(std::span< std::byte const, max_size > const &buffer)
Definition: serializer.h:81
static constexpr void serialize_at(std::span< std::byte, max_size > buffer, T item)
Definition: serializer.h:76
static constexpr std::size_t max_size
Definition: serializer.h:73
std::variant< int64_t, float, bool, string_buffer > value_type
Definition: base.h:51

converter_check<T> concept verifies that 'T' is valid overload of converter.

Use this in tests of custom converter overloads.

◆ convertible

template<typename D >
concept emlabcpp::protocol::convertible
Initial value:
= requires( D val ) {
{ traits_for< D >::max_size } -> std::convertible_to< std::size_t >;
{ traits_for< D >::min_size } -> std::convertible_to< std::size_t >;
}

This concepts limits types to types that can be declared, that is the overload of 'traits_for' is fully defined: traits_for::value_type contains definition of value produced by the declaration, traits_for::max_size contains estimated maximal size in bytes taken by the serialized value in the message.

traits_for::min_size should contain minimal size used.

◆ Endianess

emlabcpp::protocol::Endianess
Initial value:
{
using utype = std::underlying_type_t< T >

◆ fixedly_sized

template<typename T >
concept emlabcpp::protocol::fixedly_sized = traits_for< T >::min_size == traits_for< T >::max_size

◆ GROUP_ERR

constexpr auto emlabcpp::protocol::GROUP_ERR = mark( "EMCPPGRPMTCH" )
staticconstexpr

no item of group matched the content of message

◆ LOWSIZE_ERR

constexpr auto emlabcpp::protocol::LOWSIZE_ERR = mark( "EMCPPLOWSIZE" )
staticconstexpr

not enough bytes left in the message for the item

◆ mark_size

constexpr std::size_t emlabcpp::protocol::mark_size = 16
staticconstexpr

◆ max_size

constexpr std::size_t emlabcpp::protocol::max_size = userializer::max_size
staticconstexpr

◆ message_derived

template<typename T >
concept emlabcpp::protocol::message_derived = requires( T val ) { detail::message_derived_test( val ); }

concept matches any type that is message or derives from it.

◆ multiplexer_service_id

constexpr channel_type emlabcpp::protocol::multiplexer_service_id = 0
staticconstexpr

◆ packet_def

template<typename T >
concept emlabcpp::protocol::packet_def
Initial value:
= requires( T t ) {
{ T::endianess } -> std::convertible_to< std::endian >;
is_std_array_v< std::decay_t< decltype( T::prefix ) > >;
requires convertible< typename T::size_type >;
requires convertible< typename T::checksum_type >;
}
constexpr bool is_std_array_v
Definition: base.h:160

◆ register_map_void_returning

template<typename UnaryCallable , typename Registers >
concept emlabcpp::protocol::register_map_void_returning
Initial value:
=
invocable_returning< UnaryCallable, void, std::tuple_element_t< 0, Registers > >

◆ SIZE_ERR

constexpr auto emlabcpp::protocol::SIZE_ERR = mark( "EMCPPSIZE" )
staticconstexpr

◆ slot

template<typename T >
concept emlabcpp::protocol::slot
Initial value:
= requires( T s, std::span< std::byte const > data ) {
{ s.get_channel() } -> std::convertible_to< channel_type >;
{ s.on_msg( data ) } -> std::convertible_to< outcome >;
}
constexpr pointer data() noexcept
Returns pointer to first item of the storage.
Definition: static_storage.h:108

◆ UNDEFVAR_ERR

constexpr auto emlabcpp::protocol::UNDEFVAR_ERR = mark( "EMCPPUNDEFVAR" )
staticconstexpr

variant id is outside of the range for defined variant