tokio_dual_stack

Dual-stack TcpListener.
git clone https://git.philomathiclife.com/repos/tokio_dual_stack
Log | Files | Refs | README

commit 3fd21db60290f2b9360f43b428d88b1b09f3ec55
parent 1cc73441bf8fd290001b847081d8a0a930411db4
Author: Zack Newman <zack@philomathiclife.com>
Date:   Thu, 15 Jan 2026 10:47:15 -0700

export tokio

Diffstat:
MCargo.toml | 25+++++++++++++++++++++----
MREADME.md | 8++++++--
Msrc/lib.rs | 8++++++++
3 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -10,7 +10,7 @@ name = "tokio_dual_stack" readme = "README.md" repository = "https://git.philomathiclife.com/repos/tokio_dual_stack/" rust-version = "1.86.0" -version = "0.1.5" +version = "0.2.0" [lints.rust] ambiguous_negative_literals = { level = "deny", priority = -1 } @@ -44,9 +44,11 @@ rust_2021_compatibility = { level = "deny", priority = -1 } rust_2024_compatibility = { level = "deny", priority = -1 } single_use_lifetimes = { level = "deny", priority = -1 } #supertrait_item_shadowing_definition = { level = "deny", priority = -1 } +#supertrait_item_shadowing_usage = { level = "deny", priority = -1 } trivial_casts = { level = "deny", priority = -1 } trivial_numeric_casts = { level = "deny", priority = -1 } unit_bindings = { level = "deny", priority = -1 } +unknown_or_malformed_diagnostic_attributes = { level = "deny", priority = -1 } unnameable_types = { level = "deny", priority = -1 } #unqualified_local_imports = { level = "deny", priority = -1 } unreachable_pub = { level = "deny", priority = -1 } @@ -62,7 +64,6 @@ variant_size_differences = { level = "deny", priority = -1 } warnings = { level = "deny", priority = -1 } [lints.clippy] -all = { level = "deny", priority = -1 } cargo = { level = "deny", priority = -1 } complexity = { level = "deny", priority = -1 } correctness = { level = "deny", priority = -1 } @@ -76,11 +77,27 @@ suspicious = { level = "deny", priority = -1 } arbitrary_source_item_ordering = "allow" blanket_clippy_restriction_lints = "allow" implicit_return = "allow" +pub_use = "allow" return_and_then = "allow" +[package.metadata.docs.rs] +default-target = "x86_64-unknown-linux-gnu" +targets = [ + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd" +] + [dependencies] pin-project-lite = { version = "0.2.16", default-features = false } -tokio = { version = "1.47.1", default-features = false, features = ["net"] } +tokio = { version = "1.49.0", default-features = false, features = ["net"] } [dev-dependencies] -tokio = { version = "1.47.1", default-features = false, features = ["macros", "net", "rt"] } +tokio = { version = "1.49.0", default-features = false, features = ["macros", "net", "rt"] } diff --git a/README.md b/README.md @@ -55,8 +55,12 @@ at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -Before any PR is sent, `cargo clippy` and `cargo t` should be run. Additionally -`RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to ensure documentation can be built. +Before any PR is sent, `cargo clippy --all-targets`, `cargo test --all-targets`, and `cargo test --doc` should be +run using the stable and MSRV toolchains. One easy way to achieve this +is by invoking [`ci-cargo`](https://crates.io/crates/ci-cargo) as `ci-cargo clippy --all-targets test --all-targets` +in the `tokio_dual_stack` directory. + +Last, `cargo +nightly doc ` should be run to ensure documentation can be built. ### Status diff --git a/src/lib.rs b/src/lib.rs @@ -26,6 +26,7 @@ //! to `TcpListener::accept` a connection. This has the nice benefit of having a similar API to what a single //! `TcpListener` would have as well as having similar performance to a socket that does handle both IPv6 and //! IPv4 requests. +#![expect(clippy::multiple_crate_versions, reason = "windows-sys")] use core::{ net::{SocketAddr, SocketAddrV4, SocketAddrV6}, pin::Pin, @@ -34,6 +35,7 @@ use core::{ }; use pin_project_lite::pin_project; use std::io::{Error, ErrorKind, Result}; +pub use tokio; use tokio::net::{self, TcpListener, TcpSocket, TcpStream, ToSocketAddrs}; /// Prevents [`Sealed`] from being publicly implementable. mod private { @@ -384,6 +386,12 @@ impl< type Output = Result<(TcpStream, SocketAddr)>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let this = self.project(); + // Note we defer errors caused from polling a completed `Future` to the contained `tokio` `Future`s. + // The only time this `Future` can be polled after completion without an error (due to `tokio`) is + // if `fut_2` completes first, `self` is polled, then `fut_1` completes. We don't actually care + // that this happens since the correctness of the code is still fine. + // This means any bugs that could occur from polling this `Future` after completion are dependency-based + // bugs where the correct solution is to fix the bugs in `tokio`. match this.fut_1.poll(cx) { Poll::Ready(res) => Poll::Ready(res), Poll::Pending => this.fut_2.poll(cx),