blob: b0f2bef9657e6b79da8d67bcb9a92f2b7f8b371d [file] [log] [blame]
#include <stdplus/exception.hpp>
#include <stdplus/fd/ops.hpp>
#include <format>
#include <utility>
namespace stdplus
{
namespace fd
{
namespace detail
{
template <typename Fun, typename Byte, typename... Args>
static void opExact(const char* name, Fun&& fun, Fd& fd, std::span<Byte> data,
Args&&... args)
{
while (data.size() > 0)
{
auto ret = (fd.*fun)(data, std::forward<Args>(args)...);
if (ret.size() == 0)
{
throw exception::WouldBlock(
std::format("{} missing {}B", name, data.size()));
}
data = data.subspan(ret.size());
}
}
void readExact(Fd& fd, std::span<std::byte> data)
{
opExact("readExact", &Fd::read, fd, data);
}
void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags)
{
opExact("recvExact", &Fd::recv, fd, data, flags);
}
void writeExact(Fd& fd, std::span<const std::byte> data)
{
opExact("writeExact", &Fd::write, fd, data);
}
void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags)
{
opExact("sendExact", &Fd::send, fd, data, flags);
}
template <typename Fun, typename Byte, typename... Args>
static std::span<Byte> opAligned(const char* name, Fun&& fun, Fd& fd,
size_t align, std::span<Byte> data,
Args&&... args)
{
std::span<Byte> ret;
do
{
auto r = (fd.*fun)(data.subspan(ret.size()),
std::forward<Args>(args)...);
if (ret.size() != 0 && r.size() == 0)
{
throw exception::WouldBlock(
std::format("{} is {}B/{}B", name, ret.size() % align, align));
}
ret = data.subspan(0, ret.size() + r.size());
} while (ret.size() % align != 0);
return ret;
}
std::span<std::byte> readAligned(Fd& fd, size_t align, std::span<std::byte> buf)
{
return opAligned("readAligned", &Fd::read, fd, align, buf);
}
std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
RecvFlags flags)
{
return opAligned("recvAligned", &Fd::recv, fd, align, buf, flags);
}
std::span<const std::byte> writeAligned(Fd& fd, size_t align,
std::span<const std::byte> data)
{
return opAligned("writeAligned", &Fd::write, fd, align, data);
}
std::span<const std::byte> sendAligned(Fd& fd, size_t align,
std::span<const std::byte> data,
SendFlags flags)
{
return opAligned("sendAligned", &Fd::send, fd, align, data, flags);
}
} // namespace detail
} // namespace fd
} // namespace stdplus