Data Structures =============== When sending and receiving in non-buffered mode, the data are passed 'as is'. When using buffered sending/receiving, the data for multiple messages are inserted into the buffer as :cpp:struct:`netio3::BufferMsg` objects using the :cpp:class:`netio3::BufferFormatter`. The individual messages may be retrieved from the buffer using the :cpp:func:`netio3::BufferFormatter::decode()` static function. This function will call a user specified callback for each message in the buffer. .. code-block:: cpp // define the callback function auto callback = [](uint64_t tag, std::span payload, uint8_t status) { std::cout << std::format( "Received message for tag {:#x}, size {}, status {}\n", tag, payload.size(), status); }; // Process the messages in the buffer netio3::BufferFormatter::decode(buffer, &callback); Format of Data Buffer ^^^^^^^^^^^^^^^^^^^^^ 32-bit header | 8-bit status (only if non-zero) | 64-bit tag | message0 payload | 32-bit header | (8-bit status only if non-zero) | (64-bit tag only if different to message0 tag) | message1 payload... The buffer always starts with a 32-bit header word. The header word has two one-bit flags indicating whether the current message includes a status word and a tag. The first message in a buffer will always contain a tag but subsequent messages in the buffer will only contain a tag if it is different from the tag in the previous message. The status word is only present if the status is non-zero. Format of Header Word ^^^^^^^^^^^^^^^^^^^^^ ================ =================== ============ bit 31 bit 30 bits 29..0 ================ =================== ============ tag present flag status present flag message size ================ =================== ============ Format of subscription requests ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Subscription requests (:cpp:struct:`netio3::SubscriptionRequest`) are sent as JSON formatted text.