fd/ops: Add connect() call

Change-Id: Ifa835986e3b259f39fb0b467a72a002a86441cfd
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include-fd/stdplus/fd/gmock.hpp b/include-fd/stdplus/fd/gmock.hpp
index 29f8150..08c66fb 100644
--- a/include-fd/stdplus/fd/gmock.hpp
+++ b/include-fd/stdplus/fd/gmock.hpp
@@ -31,6 +31,8 @@
     MOCK_METHOD(size_t, lseek, (off_t offset, Whence whence), (override));
     MOCK_METHOD(void, truncate, (off_t size), (override));
     MOCK_METHOD(void, bind, (std::span<const std::byte> sockaddr), (override));
+    MOCK_METHOD(void, connect, (std::span<const std::byte> sockaddr),
+                (override));
     MOCK_METHOD(void, listen, (int backlog), (override));
     MOCK_METHOD((std::optional<std::tuple<int, std::span<std::byte>>>), accept,
                 (std::span<std::byte> sockaddr), (override));
diff --git a/include-fd/stdplus/fd/impl.hpp b/include-fd/stdplus/fd/impl.hpp
index 1393340..fe3af81 100644
--- a/include-fd/stdplus/fd/impl.hpp
+++ b/include-fd/stdplus/fd/impl.hpp
@@ -26,6 +26,7 @@
     size_t lseek(off_t offset, Whence whence) override;
     void truncate(off_t size) override;
     void bind(std::span<const std::byte> sockaddr) override;
+    void connect(std::span<const std::byte> sockaddr) override;
     void listen(int backlog) override;
     std::optional<std::tuple<int, std::span<std::byte>>>
         accept(std::span<std::byte> sockaddr) override;
diff --git a/include-fd/stdplus/fd/intf.hpp b/include-fd/stdplus/fd/intf.hpp
index 0b33744..293e514 100644
--- a/include-fd/stdplus/fd/intf.hpp
+++ b/include-fd/stdplus/fd/intf.hpp
@@ -134,6 +134,7 @@
     virtual size_t lseek(off_t offset, Whence whence) = 0;
     virtual void truncate(off_t size) = 0;
     virtual void bind(std::span<const std::byte> sockaddr) = 0;
+    virtual void connect(std::span<const std::byte> sockaddr) = 0;
     virtual void listen(int backlog) = 0;
     virtual std::optional<std::tuple<int, std::span<std::byte>>>
         accept(std::span<std::byte> sockaddr) = 0;
diff --git a/include-fd/stdplus/fd/ops.hpp b/include-fd/stdplus/fd/ops.hpp
index 4d0b01a..74cba26 100644
--- a/include-fd/stdplus/fd/ops.hpp
+++ b/include-fd/stdplus/fd/ops.hpp
@@ -107,6 +107,12 @@
     return fd.bind(raw::asSpan<std::byte>(sockaddr));
 }
 
+template <typename SockAddr>
+inline void connect(Fd& fd, SockAddr&& sockaddr)
+{
+    return fd.connect(raw::asSpan<std::byte>(sockaddr));
+}
+
 inline void listen(Fd& fd, int backlog)
 {
     return fd.listen(backlog);
diff --git a/src/fd/impl.cpp b/src/fd/impl.cpp
index 22a1b3b..c2d5623 100644
--- a/src/fd/impl.cpp
+++ b/src/fd/impl.cpp
@@ -117,6 +117,15 @@
         "bind");
 }
 
+void FdImpl::connect(std::span<const std::byte> sockaddr)
+{
+    CHECK_ERRNO(
+        ::connect(get(),
+                  reinterpret_cast<const struct sockaddr*>(sockaddr.data()),
+                  sockaddr.size()),
+        "connect");
+}
+
 void FdImpl::listen(int backlog)
 {
     CHECK_ERRNO(::listen(get(), backlog), "listen");