blob: e8f3636e623903436619787e78ad9f0e5d3c8159 [file] [log] [blame]
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07001#include <fmt/format.h>
Patrick Williamsd1984dd2023-05-10 16:12:44 -05002
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07003#include <stdplus/exception.hpp>
4#include <stdplus/fd/ops.hpp>
Patrick Williamsd1984dd2023-05-10 16:12:44 -05005
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07006#include <utility>
7
8namespace stdplus
9{
10namespace fd
11{
12namespace detail
13{
14
15template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050016static void opExact(const char* name, Fun&& fun, Fd& fd, std::span<Byte> data,
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070017 Args&&... args)
18{
19 while (data.size() > 0)
20 {
21 auto ret = (fd.*fun)(data, std::forward<Args>(args)...);
22 if (ret.size() == 0)
23 {
24 throw exception::WouldBlock(
25 fmt::format("{} missing {}B", name, data.size()));
26 }
27 data = data.subspan(ret.size());
28 }
29}
30
Patrick Williams68975b92022-04-27 16:00:26 -050031void readExact(Fd& fd, std::span<std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070032{
33 opExact("readExact", &Fd::read, fd, data);
34}
35
Patrick Williams68975b92022-04-27 16:00:26 -050036void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070037{
38 opExact("recvExact", &Fd::recv, fd, data, flags);
39}
40
Patrick Williams68975b92022-04-27 16:00:26 -050041void writeExact(Fd& fd, std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070042{
43 opExact("writeExact", &Fd::write, fd, data);
44}
45
Patrick Williams68975b92022-04-27 16:00:26 -050046void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070047{
48 opExact("sendExact", &Fd::send, fd, data, flags);
49}
50
51template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050052static std::span<Byte> opAligned(const char* name, Fun&& fun, Fd& fd,
53 size_t align, std::span<Byte> data,
54 Args&&... args)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070055{
Patrick Williams68975b92022-04-27 16:00:26 -050056 std::span<Byte> ret;
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070057 do
58 {
Patrick Williamsd1984dd2023-05-10 16:12:44 -050059 auto r = (fd.*fun)(data.subspan(ret.size()),
60 std::forward<Args>(args)...);
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070061 if (ret.size() != 0 && r.size() == 0)
62 {
63 throw exception::WouldBlock(
64 fmt::format("{} is {}B/{}B", name, ret.size() % align, align));
65 }
66 ret = data.subspan(0, ret.size() + r.size());
67 } while (ret.size() % align != 0);
68 return ret;
69}
70
Patrick Williams68975b92022-04-27 16:00:26 -050071std::span<std::byte> readAligned(Fd& fd, size_t align, std::span<std::byte> buf)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070072{
73 return opAligned("readAligned", &Fd::read, fd, align, buf);
74}
75
Patrick Williams68975b92022-04-27 16:00:26 -050076std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
77 RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070078{
79 return opAligned("recvAligned", &Fd::recv, fd, align, buf, flags);
80}
81
Patrick Williams68975b92022-04-27 16:00:26 -050082std::span<const std::byte> writeAligned(Fd& fd, size_t align,
83 std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070084{
85 return opAligned("writeAligned", &Fd::write, fd, align, data);
86}
87
Patrick Williams68975b92022-04-27 16:00:26 -050088std::span<const std::byte> sendAligned(Fd& fd, size_t align,
89 std::span<const std::byte> data,
90 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070091{
92 return opAligned("sendAligned", &Fd::send, fd, align, data, flags);
93}
94
95} // namespace detail
96} // namespace fd
97} // namespace stdplus