Zero-dependency (STL) header-only C++ library for definition of messages with compile-time generation of corresponding encoder/decoder/printer. MED is extensible library which can be adopted to support many type of encoding rules. Currently it includes:
- extensible implementation of non-ASN.1 octet encoding rules;
- incomplete implementation of ASN.1 BER;
- initial implementation of Google ProtoBuf encoding rules;
See overview for details and samples.
See repos for examples of med usage.
#include"med/med.hpp"template <std::size_tTAG>
using T = med::value<med::fixed<TAG, uint8_t>>;
template <typename ...T>
using M = med::mandatory<T...>;
template <typename ...T>
using O = med::optional<T...>;
using L = med::length_t<med::value<uint8_t>>;
structBYTE : med::value<uint8_t> {};
structWORD : med::value<uint16_t> {};
structTRIBYTE : med::value<med::bytes<3>> {};
structIP4 : med::value<uint32_t>
{
staticconstexprcharconst* name() { return"ip-addr"; }
};
structDWORD : med::value<uint32_t> {};
structURL : med::octet_string<med::min<5>, med::max<10>>, med::with_snapshot {};
structMSG1 : med::sequence<
M< BYTE >,
M< T<0x21>, WORD >,
M< L, URL >,
O< T<0x49>, TRIBYTE >,
O< T<0x89>, IP4 >,
O< T<0x03>, DWORD >
>{};
structMSG2 : med::set<
M< tag<0x0b>, BYTE >,
M< tag<0x21>, L, WORD >,
O< tag<0x49>, L, TRIBYTE >,
O< tag<0x89>, IP4 >,
O< tag<0x22>, L, URL >
>{};
structPROTO : med::choice<
M<T<1>, MSG1>,
M<T<2>, MSG2>
>{};//a buffer to be written with binary data of encoded messageuint8_t buffer[100];
//create encoding context to define input/output/auxiliar
med::encoder_context<> ctx{ buffer };
//the protocol to encodePROTO proto;
//set particular message in the protocolauto& msg = proto.ref<MSG2>();
//set particular fields in the message
msg.ref<BYTE>().set(0x12);
msg.ref<WORD>().set(0x3456);
//encode the protocol with octet-encoder into given contextencode(med::octet_encoder{ctx}, proto);
//now the buffer holds encoded message of size ctx.buffer().get_offset()//a binary message received in a buffer of size num_bytesPROTO proto;
med::decoder_context<> ctx;
ctx.reset(buffer, num_bytes);
decode(med::octet_decoder{ctx}, proto);
if (autoconst* msg = proto.get<MSG1>())
{
//read any message field needed
}
elseif (autoconst* msg = proto.get<MSG2>())
{
//read any message field needed
}//decode first (see above)decode(med::octet_decoder{ctx}, proto);
//use your sink to consume traces, e.g. to print them to console
your_sink sink{};
//trace protocol via your sinkmed::print(sink, proto);Any modern C++ compiler with C++20 support (see CI for the selected ones).