use std::fmt;
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::{self, Shutdown, SocketAddr};
#[cfg(any(unix, target_os = "wasi"))]
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{
AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
};
use crate::io_source::IoSource;
#[cfg(not(target_os = "wasi"))]
use crate::sys::tcp::{connect, new_for_addr};
use crate::{event, Interest, Registry, Token};
#[cfg_attr(feature = "os-poll", doc = "```")]
#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
pub struct TcpStream {
inner: IoSource<net::TcpStream>,
}
impl TcpStream {
#[cfg(not(target_os = "wasi"))]
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
let socket = new_for_addr(addr)?;
#[cfg(any(unix, target_os = "hermit"))]
let stream = unsafe { TcpStream::from_raw_fd(socket) };
#[cfg(windows)]
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
connect(&stream.inner, addr)?;
Ok(stream)
}
pub fn from_std(stream: net::TcpStream) -> TcpStream {
TcpStream {
inner: IoSource::new(stream),
}
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.inner.peer_addr()
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.inner.local_addr()
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
self.inner.set_nodelay(nodelay)
}
pub fn nodelay(&self) -> io::Result<bool> {
self.inner.nodelay()
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.inner.set_ttl(ttl)
}
pub fn ttl(&self) -> io::Result<u32> {
self.inner.ttl()
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.inner.take_error()
}
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|inner| inner.peek(buf))
}
#[cfg_attr(unix, doc = "```no_run")]
#[cfg_attr(windows, doc = "```ignore")]
pub fn try_io<F, T>(&self, f: F) -> io::Result<T>
where
F: FnOnce() -> io::Result<T>,
{
self.inner.do_io(|_| f())
}
}
impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
}
}
impl Read for &'_ TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read(buf))
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.read_vectored(bufs))
}
}
impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|mut inner| inner.flush())
}
}
impl Write for &'_ TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write(buf))
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.do_io(|mut inner| inner.write_vectored(bufs))
}
fn flush(&mut self) -> io::Result<()> {
self.inner.do_io(|mut inner| inner.flush())
}
}
impl event::Source for TcpStream {
fn register(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
self.inner.register(registry, token, interests)
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
self.inner.reregister(registry, token, interests)
}
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
self.inner.deregister(registry)
}
}
impl fmt::Debug for TcpStream {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
impl IntoRawFd for TcpStream {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
impl FromRawFd for TcpStream {
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
impl From<TcpStream> for OwnedFd {
fn from(tcp_stream: TcpStream) -> Self {
tcp_stream.inner.into_inner().into()
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
impl AsFd for TcpStream {
fn as_fd(&self) -> BorrowedFd<'_> {
self.inner.as_fd()
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
impl From<OwnedFd> for TcpStream {
fn from(fd: OwnedFd) -> Self {
TcpStream::from_std(From::from(fd))
}
}
#[cfg(windows)]
impl IntoRawSocket for TcpStream {
fn into_raw_socket(self) -> RawSocket {
self.inner.into_inner().into_raw_socket()
}
}
#[cfg(windows)]
impl AsRawSocket for TcpStream {
fn as_raw_socket(&self) -> RawSocket {
self.inner.as_raw_socket()
}
}
#[cfg(windows)]
impl FromRawSocket for TcpStream {
unsafe fn from_raw_socket(socket: RawSocket) -> TcpStream {
TcpStream::from_std(FromRawSocket::from_raw_socket(socket))
}
}
#[cfg(windows)]
impl From<TcpStream> for OwnedSocket {
fn from(tcp_stream: TcpStream) -> Self {
tcp_stream.inner.into_inner().into()
}
}
#[cfg(windows)]
impl AsSocket for TcpStream {
fn as_socket(&self) -> BorrowedSocket<'_> {
self.inner.as_socket()
}
}
#[cfg(windows)]
impl From<OwnedSocket> for TcpStream {
fn from(socket: OwnedSocket) -> Self {
TcpStream::from_std(From::from(socket))
}
}
impl From<TcpStream> for net::TcpStream {
fn from(stream: TcpStream) -> Self {
unsafe {
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
{
net::TcpStream::from_raw_fd(stream.into_raw_fd())
}
#[cfg(windows)]
{
net::TcpStream::from_raw_socket(stream.into_raw_socket())
}
}
}
}