bool TransferReceiver::writePayload(const RxFrame& frame, ITransferBuffer& buf)
{
    const uint8_t* const payload = frame.getPayloadPtr();
    const unsigned payload_len = frame.getPayloadLen();

    if (frame.isFirst())     // First frame contains CRC, we need to extract it now
    {
        if (frame.getPayloadLen() < TransferCRC::NumBytes)
        {
            return false;    // Must have been validated earlier though. I think I'm paranoid.
        }
        this_transfer_crc_ = static_cast<uint16_t>(payload[0] & 0xFF);
        this_transfer_crc_ |= static_cast<uint16_t>(static_cast<uint16_t>(payload[1] & 0xFF) << 8);  // Little endian.

        const unsigned effective_payload_len = payload_len - TransferCRC::NumBytes;
        const int res = buf.write(buffer_write_pos_, payload + TransferCRC::NumBytes, effective_payload_len);
        const bool success = res == static_cast<int>(effective_payload_len);
        if (success)
        {
            buffer_write_pos_ = static_cast<uint16_t>(buffer_write_pos_ + effective_payload_len);
        }
        return success;
    }
    else
    {
        const int res = buf.write(buffer_write_pos_, payload, payload_len);
        const bool success = res == static_cast<int>(payload_len);
        if (success)
        {
            buffer_write_pos_ = static_cast<uint16_t>(buffer_write_pos_ + payload_len);
        }
        return success;
    }
}
bool TransferReceiver::validate(const RxFrame& frame) const
{
    if (iface_index_ != frame.getIfaceIndex())
    {
        return false;
    }
    if (frame.isFirst() && !frame.isLast() && (frame.getPayloadLen() < TransferCRC::NumBytes))
    {
        UAVCAN_TRACE("TransferReceiver", "CRC expected, %s", frame.toString().c_str());
        registerError();
        return false;
    }
    if ((frame.getIndex() == Frame::MaxIndex) && !frame.isLast())
    {
        UAVCAN_TRACE("TransferReceiver", "Unterminated transfer, %s", frame.toString().c_str());
        registerError();
        return false;
    }
    if (frame.getIndex() != next_frame_index_)
    {
        UAVCAN_TRACE("TransferReceiver", "Unexpected frame index (not %i), %s",
                     int(next_frame_index_), frame.toString().c_str());
        registerError();
        return false;
    }
    if (getTidRelation(frame) != TidSame)
    {
        UAVCAN_TRACE("TransferReceiver", "Unexpected TID (current %i), %s", tid_.get(), frame.toString().c_str());
        registerError();
        return false;
    }
    return true;
}
/*
 * SingleFrameIncomingTransfer
 */
SingleFrameIncomingTransfer::SingleFrameIncomingTransfer(const RxFrame& frm)
    : IncomingTransfer(frm.getMonotonicTimestamp(), frm.getUtcTimestamp(), frm.getPriority(),
                       frm.getTransferType(), frm.getTransferID(), frm.getSrcNodeID(), frm.getIfaceIndex())
    , payload_(frm.getPayloadPtr())
    , payload_len_(uint8_t(frm.getPayloadLen()))
{
    UAVCAN_ASSERT(frm.isValid());
}
TEST(SingleFrameIncomingTransfer, Basic)
{
    using uavcan::RxFrame;
    using uavcan::SingleFrameIncomingTransfer;

    const RxFrame frame = makeFrame();
    SingleFrameIncomingTransfer it(frame);

    ASSERT_TRUE(match(it, frame, frame.getPayloadPtr(), frame.getPayloadLen()));
}