blob: b0f2bef9657e6b79da8d67bcb9a92f2b7f8b371d [file] [log] [blame]
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07001#include <stdplus/exception.hpp>
2#include <stdplus/fd/ops.hpp>
Patrick Williamsd1984dd2023-05-10 16:12:44 -05003
William A. Kennington III6417c632023-07-17 02:56:52 -07004#include <format>
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07005#include <utility>
6
7namespace stdplus
8{
9namespace fd
10{
11namespace detail
12{
13
14template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050015static void opExact(const char* name, Fun&& fun, Fd& fd, std::span<Byte> data,
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070016 Args&&... args)
17{
18 while (data.size() > 0)
19 {
20 auto ret = (fd.*fun)(data, std::forward<Args>(args)...);
21 if (ret.size() == 0)
22 {
23 throw exception::WouldBlock(
William A. Kennington III6417c632023-07-17 02:56:52 -070024 std::format("{} missing {}B", name, data.size()));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070025 }
26 data = data.subspan(ret.size());
27 }
28}
29
Patrick Williams68975b92022-04-27 16:00:26 -050030void readExact(Fd& fd, std::span<std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070031{
32 opExact("readExact", &Fd::read, fd, data);
33}
34
Patrick Williams68975b92022-04-27 16:00:26 -050035void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070036{
37 opExact("recvExact", &Fd::recv, fd, data, flags);
38}
39
Patrick Williams68975b92022-04-27 16:00:26 -050040void writeExact(Fd& fd, std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070041{
42 opExact("writeExact", &Fd::write, fd, data);
43}
44
Patrick Williams68975b92022-04-27 16:00:26 -050045void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070046{
47 opExact("sendExact", &Fd::send, fd, data, flags);
48}
49
50template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050051static std::span<Byte> opAligned(const char* name, Fun&& fun, Fd& fd,
52 size_t align, std::span<Byte> data,
53 Args&&... args)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070054{
Patrick Williams68975b92022-04-27 16:00:26 -050055 std::span<Byte> ret;
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070056 do
57 {
Patrick Williamsd1984dd2023-05-10 16:12:44 -050058 auto r = (fd.*fun)(data.subspan(ret.size()),
59 std::forward<Args>(args)...);
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070060 if (ret.size() != 0 && r.size() == 0)
61 {
62 throw exception::WouldBlock(
William A. Kennington III6417c632023-07-17 02:56:52 -070063 std::format("{} is {}B/{}B", name, ret.size() % align, align));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070064 }
65 ret = data.subspan(0, ret.size() + r.size());
66 } while (ret.size() % align != 0);
67 return ret;
68}
69
Patrick Williams68975b92022-04-27 16:00:26 -050070std::span<std::byte> readAligned(Fd& fd, size_t align, std::span<std::byte> buf)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070071{
72 return opAligned("readAligned", &Fd::read, fd, align, buf);
73}
74
Patrick Williams68975b92022-04-27 16:00:26 -050075std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
76 RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070077{
78 return opAligned("recvAligned", &Fd::recv, fd, align, buf, flags);
79}
80
Patrick Williams68975b92022-04-27 16:00:26 -050081std::span<const std::byte> writeAligned(Fd& fd, size_t align,
82 std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070083{
84 return opAligned("writeAligned", &Fd::write, fd, align, data);
85}
86
Patrick Williams68975b92022-04-27 16:00:26 -050087std::span<const std::byte> sendAligned(Fd& fd, size_t align,
88 std::span<const std::byte> data,
89 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070090{
91 return opAligned("sendAligned", &Fd::send, fd, align, data, flags);
92}
93
94} // namespace detail
95} // namespace fd
96} // namespace stdplus