use crate::raw::{
AsRawFilelike, AsRawSocketlike, FromRawFilelike, FromRawSocketlike, IntoRawFilelike,
IntoRawSocketlike, RawFilelike, RawSocketlike,
};
#[cfg(any(unix, target_os = "wasi"))]
use crate::OwnedFd;
use crate::{
AsFilelike, AsSocketlike, FromFilelike, FromSocketlike, IntoFilelike, IntoSocketlike,
OwnedFilelike, OwnedSocketlike,
};
#[cfg(windows)]
use crate::{OwnedHandle, OwnedSocket};
use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
pub unsafe trait FilelikeViewType: FromFilelike + IntoFilelike {}
pub unsafe trait SocketlikeViewType: FromSocketlike + IntoSocketlike {}
pub struct FilelikeView<'filelike, Target: FilelikeViewType> {
target: ManuallyDrop<Target>,
#[cfg(debug_assertions)]
orig: RawFilelike,
_phantom: PhantomData<&'filelike OwnedFilelike>,
}
pub struct SocketlikeView<'socketlike, Target: SocketlikeViewType> {
target: ManuallyDrop<Target>,
#[cfg(debug_assertions)]
orig: RawSocketlike,
_phantom: PhantomData<&'socketlike OwnedSocketlike>,
}
impl<Target: FilelikeViewType> FilelikeView<'_, Target> {
#[inline]
pub(crate) fn new<T: AsFilelike>(filelike: &T) -> Self {
unsafe { Self::view_raw(filelike.as_filelike().as_raw_filelike()) }
}
#[inline]
pub unsafe fn view_raw(raw: RawFilelike) -> Self {
let owned = OwnedFilelike::from_raw_filelike(raw);
Self {
target: ManuallyDrop::new(Target::from_filelike(owned)),
#[cfg(debug_assertions)]
orig: raw,
_phantom: PhantomData,
}
}
}
impl<Target: SocketlikeViewType> SocketlikeView<'_, Target> {
#[inline]
pub(crate) fn new<T: AsSocketlike>(socketlike: &T) -> Self {
unsafe { Self::view_raw(socketlike.as_socketlike().as_raw_socketlike()) }
}
#[inline]
pub unsafe fn view_raw(raw: RawSocketlike) -> Self {
let owned = OwnedSocketlike::from_raw_socketlike(raw);
Self {
target: ManuallyDrop::new(Target::from_socketlike(owned)),
#[cfg(debug_assertions)]
orig: raw,
_phantom: PhantomData,
}
}
}
impl<Target: FilelikeViewType> Deref for FilelikeView<'_, Target> {
type Target = Target;
#[inline]
fn deref(&self) -> &Self::Target {
&self.target
}
}
impl<Target: SocketlikeViewType> Deref for SocketlikeView<'_, Target> {
type Target = Target;
#[inline]
fn deref(&self) -> &Self::Target {
&self.target
}
}
impl<Target: FilelikeViewType> Drop for FilelikeView<'_, Target> {
#[inline]
fn drop(&mut self) {
let _raw = unsafe { ManuallyDrop::take(&mut self.target) }
.into_filelike()
.into_raw_filelike();
#[cfg(debug_assertions)]
debug_assert_eq!(self.orig, _raw);
}
}
impl<Target: SocketlikeViewType> Drop for SocketlikeView<'_, Target> {
#[inline]
fn drop(&mut self) {
let _raw = unsafe { ManuallyDrop::take(&mut self.target) }
.into_socketlike()
.into_raw_socketlike();
#[cfg(debug_assertions)]
debug_assert_eq!(self.orig, _raw);
}
}
impl<Target: FilelikeViewType> fmt::Debug for FilelikeView<'_, Target> {
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FilelikeView")
.field("target", &*self)
.finish()
}
}
impl<Target: SocketlikeViewType> fmt::Debug for SocketlikeView<'_, Target> {
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SocketlikeView")
.field("target", &*self)
.finish()
}
}
#[cfg(any(unix, target_os = "wasi"))]
unsafe impl FilelikeViewType for OwnedFd {}
#[cfg(windows)]
unsafe impl FilelikeViewType for OwnedHandle {}
#[cfg(windows)]
unsafe impl SocketlikeViewType for OwnedSocket {}
unsafe impl FilelikeViewType for std::fs::File {}
unsafe impl SocketlikeViewType for std::net::TcpStream {}
unsafe impl SocketlikeViewType for std::net::TcpListener {}
unsafe impl SocketlikeViewType for std::net::UdpSocket {}
#[cfg(unix)]
unsafe impl SocketlikeViewType for std::os::unix::net::UnixStream {}
#[cfg(unix)]
unsafe impl SocketlikeViewType for std::os::unix::net::UnixListener {}
#[cfg(unix)]
unsafe impl SocketlikeViewType for std::os::unix::net::UnixDatagram {}
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "os_pipe")]
unsafe impl FilelikeViewType for os_pipe::PipeWriter {}
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "os_pipe")]
unsafe impl FilelikeViewType for os_pipe::PipeReader {}
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "socket2")]
unsafe impl SocketlikeViewType for socket2::Socket {}
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "async_std")]
unsafe impl SocketlikeViewType for async_std::net::TcpStream {}
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "async_std")]
unsafe impl SocketlikeViewType for async_std::net::TcpListener {}
#[cfg(not(target_os = "wasi"))]
#[cfg(feature = "async_std")]
unsafe impl SocketlikeViewType for async_std::net::UdpSocket {}
#[cfg(unix)]
#[cfg(feature = "async_std")]
unsafe impl SocketlikeViewType for async_std::os::unix::net::UnixStream {}
#[cfg(unix)]
#[cfg(feature = "async_std")]
unsafe impl SocketlikeViewType for async_std::os::unix::net::UnixListener {}
#[cfg(unix)]
#[cfg(feature = "async_std")]
unsafe impl SocketlikeViewType for async_std::os::unix::net::UnixDatagram {}
#[cfg(feature = "mio")]
unsafe impl SocketlikeViewType for mio::net::TcpStream {}
#[cfg(feature = "mio")]
unsafe impl SocketlikeViewType for mio::net::TcpListener {}
#[cfg(feature = "mio")]
unsafe impl SocketlikeViewType for mio::net::UdpSocket {}
#[cfg(unix)]
#[cfg(feature = "mio")]
unsafe impl SocketlikeViewType for mio::net::UnixDatagram {}
#[cfg(unix)]
#[cfg(feature = "mio")]
unsafe impl SocketlikeViewType for mio::net::UnixListener {}
#[cfg(unix)]
#[cfg(feature = "mio")]
unsafe impl SocketlikeViewType for mio::net::UnixStream {}
#[cfg(unix)]
#[cfg(feature = "mio")]
unsafe impl FilelikeViewType for mio::unix::pipe::Receiver {}
#[cfg(unix)]
#[cfg(feature = "mio")]
unsafe impl FilelikeViewType for mio::unix::pipe::Sender {}