io::IReader

The interface IReader is the counterpart of io::IWriter and an abstraction to read chunks of bytes with variable length from a data channel.

Public API

/**
 * Returns the maximum number of bytes that may be read in one peek call
 */
virtual size_t maxSize() const = 0;

/**
 * Returns a slice to the next piece of available data.
 * \return - Slice of bytes if underlying queue was not empty
 *         - Empty slice otherwise
 */
virtual ::estd::slice<uint8_t> peek() const = 0;

/**
 * Releases the memory that the last peek() call returned.
 *
 * Calling release() makes a new call to peek() mandatory! The previously peeked data must not
 * be used anymore.
 */
virtual void release() = 0;

Usage of API

The next sequence diagram visualizes the two step peek() and release() API. After a call to peek() returns a slice of data with size greater than zero, the user can consume this data. A call to release() frees the data again, also invalidating it for the user. It must not be used anymore after calling release().

actor SW
SW -> IReader : auto d = peek()
alt d.size() > 0 case
    SW -> SW  : consume d
    SW -> IReader : release()
end

Example

/**
 * Tries to receive a CanFrame from a given IReader.
 * \param frame CanFrame to receive to, i.e. frame provides memory to copy to.
 * \param reader IReader to try to receive a frame from.
 * \return true if a frame was read, false otherwise.
 */
bool receiveCanFrame(CanFrame& frame, ::io::IReader& reader)
{
    auto data = reader.peek();
    if (data.size() < sizeof(uint32_t))
    {
        // No frame available (A frame consists of at least uint32_t id)
        return false;
    }
    // Copy data to frame. We expect a big endian 32bit id followed by the actual data.
    frame.id = ::estd::memory::take<::estd::be_uint32_t>(data);
    ::estd::memory::copy(frame.data, data);
    frame.data.trim(data.size());
    // Release data to channel.
    reader.release();
    return true;
}