#include <balancer/kernel/process_common/fixed_buffer_io.h>

#include <library/cpp/coroutine/engine/network.h>

namespace NSrvKernel {
    void TFixedBufferContReader::ReadTheWholeThing(TCont *cont, SOCKET fd) {
        while (Remaining_) {
            auto status = NCoro::ReadI(cont, fd, Buffer_ + Scanned_, Remaining_);
            if (status.Status() == EWOULDBLOCK || status.Status() == EAGAIN) {
                cont->SleepT(TDuration::Seconds(1));
                continue;
            }

            size_t piece = status.Checked();

            if (piece == 0) {
                ythrow yexception{} << "fd signaled EOF before buffer was read";
            }

            Scanned_ += piece;
            Remaining_ -= piece;
        }
    }

    void TFixedBufferContReader::ReadBuffer(TCont* cont, SOCKET fd, char *buffer, size_t size) {
        TFixedBufferContReader reader(buffer, size);
        reader.ReadTheWholeThing(cont, fd);
    }

    void TFixedBufferContWriter::WriteTheWholeThing(TCont* cont, SOCKET fd) {
        while (Remaining_) {
            size_t piece = NCoro::WriteI(cont, fd, Buffer_ + Written_, Remaining_).Checked();

            Written_ += piece;
            Remaining_ -= piece;
        }
    }

    void TFixedBufferContWriter::WriteBuffer(TCont* cont, SOCKET fd, char *buffer, size_t size) {
        TFixedBufferContWriter writer(buffer, size);
        writer.WriteTheWholeThing(cont, fd);
    }
}

