seq-runtime 7.7.3

Runtime library for the Seq programming language
Documentation
//! Type-erased connection handle for the HTTP client.
//!
//! The pool and request orchestrator hold `Box<dyn HttpStream + Send>`
//! rather than the runtime-wide `StreamKind` enum. Why: an enum that
//! has both a TCP and a TLS arm pulls in *both* arms' drop glue at any
//! reachable drop site, which forces rustls's per-connection drop
//! chain into the final binary even when no Seq program uses
//! `net.http.*` or `net.tls.client`. (See `docs/design/done/NO_DEAD_CODE.md`
//! and the PR4 review thread.)
//!
//! A trait object decouples the two: the vtable for the TLS-wrapped
//! stream is emitted only inside `tls::dial_tls`, which is itself
//! unreachable from a hello-world binary. `--gc-sections` then strips
//! the rustls types out cleanly.
//!
//! All read/write operations dispatch through the vtable. The extra
//! indirection is one nanosecond per call — negligible against the
//! micro-to-millisecond latency of a TCP/TLS round-trip.

use std::io::{Read, Write};
use std::os::fd::RawFd;
use std::time::Duration;

/// What the HTTP client needs from a connection: byte stream IO plus
/// the underlying TCP fd (for the pool's half-closed peek) plus the
/// ability to set per-operation timeouts on the underlying may
/// TcpStream (for the request/response deadline pass).
pub(crate) trait HttpStream: Read + Write + Send {
    /// Underlying TCP file descriptor, even for TLS-wrapped streams.
    /// Used by the pool's non-blocking `poll(POLLIN, 0)` reuse check.
    fn raw_fd(&self) -> RawFd;

    /// Set the underlying may TcpStream's per-read timeout. Returns
    /// any IO error from the syscall verbatim. `None` clears the
    /// deadline (read can block indefinitely).
    fn set_read_timeout(&mut self, dur: Option<Duration>) -> std::io::Result<()>;

    /// Set the underlying may TcpStream's per-write timeout.
    fn set_write_timeout(&mut self, dur: Option<Duration>) -> std::io::Result<()>;
}

impl HttpStream for may::net::TcpStream {
    fn raw_fd(&self) -> RawFd {
        use std::os::fd::AsRawFd;
        self.as_raw_fd()
    }
    fn set_read_timeout(&mut self, dur: Option<Duration>) -> std::io::Result<()> {
        may::net::TcpStream::set_read_timeout(self, dur)
    }
    fn set_write_timeout(&mut self, dur: Option<Duration>) -> std::io::Result<()> {
        may::net::TcpStream::set_write_timeout(self, dur)
    }
}

impl HttpStream for rustls::StreamOwned<rustls::ClientConnection, may::net::TcpStream> {
    fn raw_fd(&self) -> RawFd {
        use std::os::fd::AsRawFd;
        // `StreamOwned.sock` is a public field per rustls 0.23
        // (`pub sock: T`). If a future rustls release ever makes it
        // private, this access breaks compilation and we replace it
        // with a sock-accessor wrapper. Documented here so a future
        // bump doesn't trigger a confused-error hunt.
        self.sock.as_raw_fd()
    }
    fn set_read_timeout(&mut self, dur: Option<Duration>) -> std::io::Result<()> {
        self.sock.set_read_timeout(dur)
    }
    fn set_write_timeout(&mut self, dur: Option<Duration>) -> std::io::Result<()> {
        self.sock.set_write_timeout(dur)
    }
}

pub(crate) type Conn = Box<dyn HttpStream + Send>;