#[cfg(all(windows, feature = "os_pipe"))]
use os_pipe::{PipeReader, PipeWriter};
#[cfg(unix)]
use std::os::unix::{
io::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
net::UnixStream,
};
#[cfg(target_os = "wasi")]
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::{
fmt,
fs::File,
io::{self, IoSlice, IoSliceMut, Read, Write},
marker::PhantomData,
mem::ManuallyDrop,
net::{TcpListener, TcpStream, UdpSocket},
ops::{Deref, DerefMut},
};
#[cfg(windows)]
use {
super::{AsRawHandleOrSocket, RawHandleOrSocket},
std::{
os::windows::io::{
AsRawHandle, AsRawSocket, FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket,
RawHandle, RawSocket,
},
process::{ChildStderr, ChildStdin, ChildStdout},
},
};
#[allow(clippy::module_name_repetitions)]
pub trait AsUnsafeHandle {
fn as_unsafe_handle(&self) -> UnsafeHandle;
}
#[allow(clippy::module_name_repetitions)]
pub trait IntoUnsafeHandle {
fn into_unsafe_handle(self) -> UnsafeHandle;
}
pub trait AsUnsafeFile {
fn as_unsafe_file(&self) -> UnsafeFile;
#[inline]
fn as_file(&self) -> View<File> {
let unsafe_file = self.as_unsafe_file();
let file = unsafe { File::from_unsafe_file(unsafe_file) };
View {
target: ManuallyDrop::new(file),
_phantom_data: PhantomData,
}
}
}
pub trait IntoUnsafeFile {
fn into_unsafe_file(self) -> UnsafeFile;
#[inline]
fn into_file(self) -> File
where
Self: Sized,
{
let unsafe_file = self.into_unsafe_file();
unsafe { File::from_unsafe_file(unsafe_file) }
}
}
pub trait FromUnsafeFile {
unsafe fn from_unsafe_file(unsafe_file: UnsafeFile) -> Self;
}
pub trait AsUnsafeSocket {
fn as_unsafe_socket(&self) -> UnsafeSocket;
#[inline]
fn as_tcp_stream(&self) -> View<TcpStream> {
let unsafe_socket = self.as_unsafe_socket();
let tcp_stream = unsafe { TcpStream::from_unsafe_socket(unsafe_socket) };
View {
target: ManuallyDrop::new(tcp_stream),
_phantom_data: PhantomData,
}
}
#[inline]
fn as_tcp_listener(&self) -> View<TcpListener> {
let unsafe_socket = self.as_unsafe_socket();
let tcp_listener = unsafe { TcpListener::from_unsafe_socket(unsafe_socket) };
View {
target: ManuallyDrop::new(tcp_listener),
_phantom_data: PhantomData,
}
}
#[inline]
fn as_udp_socket(&self) -> View<UdpSocket> {
let unsafe_socket = self.as_unsafe_socket();
let udp_socket = unsafe { UdpSocket::from_unsafe_socket(unsafe_socket) };
View {
target: ManuallyDrop::new(udp_socket),
_phantom_data: PhantomData,
}
}
#[cfg(unix)]
#[inline]
fn as_unix_stream(&self) -> View<UnixStream> {
let unsafe_socket = self.as_unsafe_socket();
let unix_stream = unsafe { UnixStream::from_unsafe_socket(unsafe_socket) };
View {
target: ManuallyDrop::new(unix_stream),
_phantom_data: PhantomData,
}
}
}
pub trait IntoUnsafeSocket {
fn into_unsafe_socket(self) -> UnsafeSocket;
#[inline]
fn into_tcp_stream(self) -> TcpStream
where
Self: Sized,
{
let unsafe_socket = self.into_unsafe_socket();
unsafe { TcpStream::from_unsafe_socket(unsafe_socket) }
}
}
pub trait FromUnsafeSocket {
unsafe fn from_unsafe_socket(unsafe_socket: UnsafeSocket) -> Self;
}
#[derive(Copy, Clone)]
pub struct UnsafeHandle(InnerFileOrSocket);
#[derive(Copy, Clone)]
pub struct UnsafeFile(InnerFile);
#[derive(Copy, Clone)]
pub struct UnsafeSocket(InnerSocket);
#[derive(Copy, Clone)]
pub struct UnsafeReadable(InnerFileOrSocket);
#[derive(Copy, Clone)]
pub struct UnsafeWriteable(InnerFileOrSocket);
#[cfg(not(windows))]
type InnerFileOrSocket = RawFd;
#[cfg(not(windows))]
type InnerFile = RawFd;
#[cfg(not(windows))]
type InnerSocket = RawFd;
#[cfg(windows)]
type InnerFileOrSocket = RawHandleOrSocket;
#[cfg(windows)]
type InnerFile = RawHandle;
#[cfg(windows)]
type InnerSocket = RawSocket;
pub struct View<'resource, Target: AsUnsafeHandle> {
target: ManuallyDrop<Target>,
_phantom_data: PhantomData<&'resource ()>,
}
impl<'resource, Target: AsUnsafeHandle> Deref for View<'resource, Target> {
type Target = Target;
#[inline]
fn deref(&self) -> &Self::Target {
&self.target
}
}
impl<'resource, Target: AsUnsafeHandle> DerefMut for View<'resource, Target> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.target
}
}
impl UnsafeHandle {
#[inline]
#[must_use]
pub const unsafe fn as_readable(self) -> UnsafeReadable {
UnsafeReadable(self.0)
}
#[inline]
#[must_use]
pub const unsafe fn as_writeable(self) -> UnsafeWriteable {
UnsafeWriteable(self.0)
}
#[inline]
#[must_use]
pub unsafe fn eq(self, other: Self) -> bool {
PartialEq::eq(&self.0, &other.0)
}
#[cfg(not(windows))]
#[inline]
#[must_use]
pub const fn from_raw_fd(raw_fd: RawFd) -> Self {
Self(raw_fd)
}
#[cfg(windows)]
#[inline]
pub fn from_raw_handle(raw_handle: RawHandle) -> Self {
Self(RawHandleOrSocket::Handle(raw_handle))
}
#[cfg(windows)]
#[inline]
pub fn from_raw_socket(raw_socket: RawSocket) -> Self {
Self(RawHandleOrSocket::Socket(raw_socket))
}
#[cfg(windows)]
#[inline]
pub fn from_raw_handle_or_socket(raw_handle_or_socket: RawHandleOrSocket) -> Self {
Self(raw_handle_or_socket)
}
}
#[cfg(not(windows))]
impl UnsafeFile {
#[inline]
#[must_use]
pub const fn from_raw_fd(raw_fd: RawFd) -> Self {
Self(raw_fd)
}
}
#[cfg(windows)]
impl UnsafeFile {
#[inline]
pub fn from_raw_handle(raw_handle: RawHandle) -> Self {
Self(raw_handle)
}
}
#[cfg(not(windows))]
impl UnsafeSocket {
#[inline]
#[must_use]
pub const fn from_raw_fd(raw_fd: RawFd) -> Self {
Self(raw_fd)
}
}
#[cfg(windows)]
impl UnsafeSocket {
#[inline]
pub fn from_raw_socket(raw_socket: RawSocket) -> Self {
Self(raw_socket)
}
}
#[cfg(not(windows))]
impl<T: AsRawFd> AsUnsafeHandle for T {
#[inline]
fn as_unsafe_handle(&self) -> UnsafeHandle {
UnsafeHandle(self.as_raw_fd())
}
}
#[cfg(not(windows))]
impl<T: AsRawFd> AsUnsafeFile for T {
#[inline]
fn as_unsafe_file(&self) -> UnsafeFile {
UnsafeFile(self.as_raw_fd())
}
}
#[cfg(not(windows))]
impl<T: AsRawFd> AsUnsafeSocket for T {
#[inline]
fn as_unsafe_socket(&self) -> UnsafeSocket {
UnsafeSocket(self.as_raw_fd())
}
}
#[cfg(not(windows))]
impl<T: IntoRawFd> IntoUnsafeHandle for T {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle(self.into_raw_fd())
}
}
#[cfg(not(windows))]
impl<T: IntoRawFd> IntoUnsafeFile for T {
#[inline]
fn into_unsafe_file(self) -> UnsafeFile {
UnsafeFile(self.into_raw_fd())
}
}
#[cfg(not(windows))]
impl<T: IntoRawFd> IntoUnsafeSocket for T {
#[inline]
fn into_unsafe_socket(self) -> UnsafeSocket {
UnsafeSocket(self.into_raw_fd())
}
}
#[cfg(not(windows))]
impl<T: FromRawFd> FromUnsafeFile for T {
#[inline]
unsafe fn from_unsafe_file(unsafe_file: UnsafeFile) -> Self {
Self::from_raw_fd(unsafe_file.0)
}
}
#[cfg(not(windows))]
impl<T: FromRawFd> FromUnsafeSocket for T {
#[inline]
unsafe fn from_unsafe_socket(unsafe_socket: UnsafeSocket) -> Self {
Self::from_raw_fd(unsafe_socket.0)
}
}
#[cfg(not(windows))]
impl AsRawFd for UnsafeHandle {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
#[cfg(not(windows))]
impl AsRawFd for UnsafeReadable {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
#[cfg(not(windows))]
impl AsRawFd for UnsafeWriteable {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
#[cfg(not(windows))]
impl AsRawFd for UnsafeFile {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
#[cfg(not(windows))]
impl AsRawFd for UnsafeSocket {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
#[cfg(windows)]
impl<T: AsRawHandleOrSocket> AsUnsafeHandle for T {
#[inline]
fn as_unsafe_handle(&self) -> UnsafeHandle {
UnsafeHandle(self.as_raw_handle_or_socket())
}
}
#[cfg(windows)]
impl<T: AsRawHandle> AsUnsafeFile for T {
#[inline]
fn as_unsafe_file(&self) -> UnsafeFile {
UnsafeFile(AsRawHandle::as_raw_handle(self))
}
}
#[cfg(windows)]
impl<T: AsRawSocket> AsUnsafeSocket for T {
#[inline]
fn as_unsafe_socket(&self) -> UnsafeSocket {
UnsafeSocket(AsRawSocket::as_raw_socket(self))
}
}
#[cfg(windows)]
impl<T: IntoRawHandle> IntoUnsafeFile for T {
#[inline]
fn into_unsafe_file(self) -> UnsafeFile {
UnsafeFile(Self::into_raw_handle(self))
}
}
#[cfg(windows)]
impl<T: IntoRawSocket> IntoUnsafeSocket for T {
#[inline]
fn into_unsafe_socket(self) -> UnsafeSocket {
UnsafeSocket(IntoRawSocket::into_raw_socket(self))
}
}
#[cfg(windows)]
impl<T: FromRawHandle> FromUnsafeFile for T {
#[inline]
unsafe fn from_unsafe_file(unsafe_file: UnsafeFile) -> Self {
Self::from_raw_handle(unsafe_file.0)
}
}
#[cfg(windows)]
impl<T: FromRawSocket> FromUnsafeSocket for T {
#[inline]
unsafe fn from_unsafe_socket(unsafe_socket: UnsafeSocket) -> Self {
Self::from_raw_socket(unsafe_socket.0)
}
}
#[cfg(windows)]
impl IntoUnsafeHandle for File {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_handle(Self::into_raw_handle(self))
}
}
#[cfg(windows)]
impl IntoUnsafeHandle for ChildStdin {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_handle(Self::into_raw_handle(self))
}
}
#[cfg(windows)]
impl IntoUnsafeHandle for ChildStdout {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_handle(Self::into_raw_handle(self))
}
}
#[cfg(windows)]
impl IntoUnsafeHandle for ChildStderr {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_handle(Self::into_raw_handle(self))
}
}
#[cfg(windows)]
impl IntoUnsafeHandle for TcpStream {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_socket(Self::into_raw_socket(self))
}
}
#[cfg(all(windows, feature = "os_pipe"))]
impl IntoUnsafeHandle for PipeReader {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_handle(Self::into_raw_handle(self))
}
}
#[cfg(all(windows, feature = "os_pipe"))]
impl IntoUnsafeHandle for PipeWriter {
#[inline]
fn into_unsafe_handle(self) -> UnsafeHandle {
UnsafeHandle::from_raw_handle(Self::into_raw_handle(self))
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for UnsafeHandle {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for UnsafeReadable {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for UnsafeWriteable {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
self.0
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for UnsafeFile {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
RawHandleOrSocket::Handle(self.0)
}
}
#[cfg(windows)]
impl AsRawHandle for UnsafeFile {
#[inline]
fn as_raw_handle(&self) -> RawHandle {
self.0
}
}
#[cfg(windows)]
impl AsRawHandleOrSocket for UnsafeSocket {
#[inline]
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
RawHandleOrSocket::Socket(self.0)
}
}
#[cfg(windows)]
impl AsRawSocket for UnsafeSocket {
#[inline]
fn as_raw_socket(&self) -> RawSocket {
self.0
}
}
#[cfg(not(windows))]
impl Read for UnsafeReadable {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.as_file().read(buf)
}
#[inline]
fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
self.as_file().read_vectored(bufs)
}
#[cfg(can_vector)]
#[inline]
fn is_read_vectored(&self) -> bool {
self.as_file().is_read_vectored()
}
#[inline]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.as_file().read_to_end(buf)
}
#[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.as_file().read_to_string(buf)
}
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.as_file().read_exact(buf)
}
}
#[cfg(windows)]
impl Read for UnsafeReadable {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => unsafe { as_file(self, raw_handle) }.read(buf),
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.read(buf)
}
}
}
#[inline]
fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.read_vectored(bufs)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.read_vectored(bufs)
}
}
}
#[cfg(can_vector)]
#[inline]
fn is_read_vectored(&self) -> bool {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.is_read_vectored()
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.is_read_vectored()
}
}
}
#[inline]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.read_to_end(buf)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.read_to_end(buf)
}
}
}
#[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.read_to_string(buf)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.read_to_string(buf)
}
}
}
#[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.read_exact(buf)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.read_exact(buf)
}
}
}
}
#[cfg(not(windows))]
impl Write for UnsafeWriteable {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.as_file().write(buf)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
self.as_file().flush()
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
self.as_file().write_vectored(bufs)
}
#[cfg(can_vector)]
#[inline]
fn is_write_vectored(&self) -> bool {
self.as_file().is_write_vectored()
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.as_file().write_all(buf)
}
#[cfg(write_all_vectored)]
#[inline]
fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> {
self.as_file().write_all_vectored(bufs)
}
#[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
self.as_file().write_fmt(fmt)
}
}
#[cfg(windows)]
impl Write for UnsafeWriteable {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.write(buf)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.write(buf)
}
}
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => unsafe { as_file(self, raw_handle) }.flush(),
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.flush()
}
}
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.write_vectored(bufs)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.write_vectored(bufs)
}
}
}
#[cfg(can_vector)]
#[inline]
fn is_write_vectored(&self) -> bool {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.is_write_vectored()
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.is_write_vectored()
}
}
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.write_all(buf)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.write_all(buf)
}
}
}
#[cfg(write_all_vectored)]
#[inline]
fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.write_all_vectored(bufs)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.write_all_vectored(bufs)
}
}
}
#[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
match self.0 {
RawHandleOrSocket::Handle(raw_handle) => {
unsafe { as_file(self, raw_handle) }.write_fmt(fmt)
}
RawHandleOrSocket::Socket(raw_socket) => {
unsafe { as_tcp_stream(self, raw_socket) }.write_fmt(fmt)
}
}
}
}
#[cfg(windows)]
#[inline]
unsafe fn as_file<T: AsRawHandleOrSocket>(_t: &T, raw_handle: RawHandle) -> View<File> {
View {
target: ManuallyDrop::new(File::from_raw_handle(raw_handle)),
_phantom_data: PhantomData,
}
}
#[cfg(windows)]
#[inline]
unsafe fn as_tcp_stream<T: AsRawHandleOrSocket>(_t: &T, raw_socket: RawSocket) -> View<TcpStream> {
View {
target: ManuallyDrop::new(TcpStream::from_raw_socket(raw_socket)),
_phantom_data: PhantomData,
}
}
#[cfg(not(windows))]
impl fmt::Debug for UnsafeHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeHandle")
.field("raw_fd", &self.as_raw_fd())
.finish()
}
}
#[cfg(windows)]
impl fmt::Debug for UnsafeHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeHandle")
.field("raw_handle_or_socket", &self.as_raw_handle_or_socket())
.finish()
}
}
#[cfg(not(windows))]
impl fmt::Debug for UnsafeFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeFile")
.field("raw_fd", &self.0)
.finish()
}
}
#[cfg(windows)]
impl fmt::Debug for UnsafeFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeFile")
.field("raw_handle", &self.0)
.finish()
}
}
#[cfg(not(windows))]
impl fmt::Debug for UnsafeSocket {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeSocket")
.field("raw_fd", &self.0)
.finish()
}
}
#[cfg(windows)]
impl fmt::Debug for UnsafeSocket {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeSocket")
.field("raw_socket", &self.0)
.finish()
}
}
#[cfg(not(windows))]
impl fmt::Debug for UnsafeReadable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeReadable")
.field("raw_fd", &self.0)
.finish()
}
}
#[cfg(windows)]
impl fmt::Debug for UnsafeReadable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeReadable")
.field("raw_handle_or_socket", &self.0)
.finish()
}
}
#[cfg(not(windows))]
impl fmt::Debug for UnsafeWriteable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeWriteable")
.field("raw_fd", &self.0)
.finish()
}
}
#[cfg(windows)]
impl fmt::Debug for UnsafeWriteable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UnsafeWriteable")
.field("raw_handle_or_socket", &self.0)
.finish()
}
}