use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
#[cfg(unix)]
use std::os::unix::io::{AsFd, AsRawFd, FromRawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, AsSocket, FromRawSocket};
use crate::Socket;
pub struct SockRef<'s> {
socket: ManuallyDrop<Socket>,
_lifetime: PhantomData<&'s Socket>,
}
impl<'s> Deref for SockRef<'s> {
type Target = Socket;
fn deref(&self) -> &Self::Target {
&self.socket
}
}
#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
impl<'s, S> From<&'s S> for SockRef<'s>
where
S: AsFd,
{
fn from(socket: &'s S) -> Self {
let fd = socket.as_fd().as_raw_fd();
assert!(fd >= 0);
SockRef {
socket: ManuallyDrop::new(unsafe { Socket::from_raw_fd(fd) }),
_lifetime: PhantomData,
}
}
}
#[cfg(windows)]
#[cfg_attr(docsrs, doc(cfg(windows)))]
impl<'s, S> From<&'s S> for SockRef<'s>
where
S: AsSocket,
{
fn from(socket: &'s S) -> Self {
let socket = socket.as_socket().as_raw_socket();
assert!(socket != windows_sys::Win32::Networking::WinSock::INVALID_SOCKET as _);
SockRef {
socket: ManuallyDrop::new(unsafe { Socket::from_raw_socket(socket) }),
_lifetime: PhantomData,
}
}
}
impl fmt::Debug for SockRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SockRef")
.field("raw", &self.socket.as_raw())
.field("local_addr", &self.socket.local_addr().ok())
.field("peer_addr", &self.socket.peer_addr().ok())
.finish()
}
}