blob: d47dbb34e335e865294cd8af72f454ebfded6956 [file] [log] [blame]
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07001#include <fmt/format.h>
2#include <stdplus/exception.hpp>
3#include <stdplus/fd/ops.hpp>
4#include <utility>
5
6namespace stdplus
7{
8namespace fd
9{
10namespace detail
11{
12
13template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050014static void opExact(const char* name, Fun&& fun, Fd& fd, std::span<Byte> data,
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070015 Args&&... args)
16{
17 while (data.size() > 0)
18 {
19 auto ret = (fd.*fun)(data, std::forward<Args>(args)...);
20 if (ret.size() == 0)
21 {
22 throw exception::WouldBlock(
23 fmt::format("{} missing {}B", name, data.size()));
24 }
25 data = data.subspan(ret.size());
26 }
27}
28
Patrick Williams68975b92022-04-27 16:00:26 -050029void readExact(Fd& fd, std::span<std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070030{
31 opExact("readExact", &Fd::read, fd, data);
32}
33
Patrick Williams68975b92022-04-27 16:00:26 -050034void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070035{
36 opExact("recvExact", &Fd::recv, fd, data, flags);
37}
38
Patrick Williams68975b92022-04-27 16:00:26 -050039void writeExact(Fd& fd, std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070040{
41 opExact("writeExact", &Fd::write, fd, data);
42}
43
Patrick Williams68975b92022-04-27 16:00:26 -050044void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070045{
46 opExact("sendExact", &Fd::send, fd, data, flags);
47}
48
49template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050050static std::span<Byte> opAligned(const char* name, Fun&& fun, Fd& fd,
51 size_t align, std::span<Byte> data,
52 Args&&... args)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070053{
Patrick Williams68975b92022-04-27 16:00:26 -050054 std::span<Byte> ret;
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070055 do
56 {
57 auto r =
58 (fd.*fun)(data.subspan(ret.size()), std::forward<Args>(args)...);
59 if (ret.size() != 0 && r.size() == 0)
60 {
61 throw exception::WouldBlock(
62 fmt::format("{} is {}B/{}B", name, ret.size() % align, align));
63 }
64 ret = data.subspan(0, ret.size() + r.size());
65 } while (ret.size() % align != 0);
66 return ret;
67}
68
Patrick Williams68975b92022-04-27 16:00:26 -050069std::span<std::byte> readAligned(Fd& fd, size_t align, std::span<std::byte> buf)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070070{
71 return opAligned("readAligned", &Fd::read, fd, align, buf);
72}
73
Patrick Williams68975b92022-04-27 16:00:26 -050074std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
75 RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070076{
77 return opAligned("recvAligned", &Fd::recv, fd, align, buf, flags);
78}
79
Patrick Williams68975b92022-04-27 16:00:26 -050080std::span<const std::byte> writeAligned(Fd& fd, size_t align,
81 std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070082{
83 return opAligned("writeAligned", &Fd::write, fd, align, data);
84}
85
Patrick Williams68975b92022-04-27 16:00:26 -050086std::span<const std::byte> sendAligned(Fd& fd, size_t align,
87 std::span<const std::byte> data,
88 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070089{
90 return opAligned("sendAligned", &Fd::send, fd, align, data, flags);
91}
92
93} // namespace detail
94} // namespace fd
95} // namespace stdplus