Auto merge of #27064 - alexcrichton:into-raw-os, r=brson
This commit is an implementation of [RFC 1174][rfc] which adds three new traits to the standard library: * `IntoRawFd` - implemented on Unix for all I/O types (files, sockets, etc) * `IntoRawHandle` - implemented on Windows for files, processes, etc * `IntoRawSocket` - implemented on Windows for networking types [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1174-into-raw-fd-socket-handle-traits.md Closes #27062
This commit is contained in:
commit
47265bbf37
16 changed files with 195 additions and 15 deletions
|
@ -24,8 +24,8 @@ use ffi::OsString;
|
|||
use io::{self, SeekFrom, Seek, Read, Write};
|
||||
use path::{Path, PathBuf};
|
||||
use sys::fs as fs_imp;
|
||||
use sys_common::{AsInnerMut, FromInner, AsInner};
|
||||
use sys_common::io::read_to_end_uninitialized;
|
||||
use sys_common::{AsInnerMut, FromInner, AsInner, IntoInner};
|
||||
use vec::Vec;
|
||||
|
||||
/// A reference to an open file on the filesystem.
|
||||
|
@ -317,6 +317,11 @@ impl FromInner<fs_imp::File> for File {
|
|||
File { inner: f }
|
||||
}
|
||||
}
|
||||
impl IntoInner<fs_imp::File> for File {
|
||||
fn into_inner(self) -> fs_imp::File {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
|
|
@ -17,9 +17,9 @@ use io::prelude::*;
|
|||
use fmt;
|
||||
use io;
|
||||
use net::{ToSocketAddrs, SocketAddr, Shutdown};
|
||||
use sys_common::net as net_imp;
|
||||
use sys_common::{AsInner, FromInner};
|
||||
use sys_common::io::read_to_end_uninitialized;
|
||||
use sys_common::net as net_imp;
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
use time::Duration;
|
||||
|
||||
/// A structure which represents a TCP stream between a local socket and a
|
||||
|
@ -220,6 +220,10 @@ impl FromInner<net_imp::TcpStream> for TcpStream {
|
|||
fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) }
|
||||
}
|
||||
|
||||
impl IntoInner<net_imp::TcpStream> for TcpStream {
|
||||
fn into_inner(self) -> net_imp::TcpStream { self.0 }
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
|
@ -298,6 +302,10 @@ impl FromInner<net_imp::TcpListener> for TcpListener {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoInner<net_imp::TcpListener> for TcpListener {
|
||||
fn into_inner(self) -> net_imp::TcpListener { self.0 }
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpListener {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
|
|
|
@ -17,7 +17,7 @@ use fmt;
|
|||
use io::{self, Error, ErrorKind};
|
||||
use net::{ToSocketAddrs, SocketAddr, IpAddr};
|
||||
use sys_common::net as net_imp;
|
||||
use sys_common::{AsInner, FromInner};
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
use time::Duration;
|
||||
|
||||
/// A User Datagram Protocol socket.
|
||||
|
@ -174,6 +174,10 @@ impl FromInner<net_imp::UdpSocket> for UdpSocket {
|
|||
fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) }
|
||||
}
|
||||
|
||||
impl IntoInner<net_imp::UdpSocket> for UdpSocket {
|
||||
fn into_inner(self) -> net_imp::UdpSocket { self.0 }
|
||||
}
|
||||
|
||||
impl fmt::Debug for UdpSocket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
|
|
|
@ -23,7 +23,7 @@ use path;
|
|||
use sync::mpsc::{channel, Receiver};
|
||||
use sys::pipe::{self, AnonPipe};
|
||||
use sys::process as imp;
|
||||
use sys_common::{AsInner, AsInnerMut, FromInner};
|
||||
use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
use thread;
|
||||
|
||||
/// Representation of a running or exited child process.
|
||||
|
@ -71,6 +71,10 @@ impl AsInner<imp::Process> for Child {
|
|||
fn as_inner(&self) -> &imp::Process { &self.handle }
|
||||
}
|
||||
|
||||
impl IntoInner<imp::Process> for Child {
|
||||
fn into_inner(self) -> imp::Process { self.handle }
|
||||
}
|
||||
|
||||
/// A handle to a child procesess's stdin
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ChildStdin {
|
||||
|
@ -92,6 +96,10 @@ impl AsInner<AnonPipe> for ChildStdin {
|
|||
fn as_inner(&self) -> &AnonPipe { &self.inner }
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for ChildStdin {
|
||||
fn into_inner(self) -> AnonPipe { self.inner }
|
||||
}
|
||||
|
||||
/// A handle to a child procesess's stdout
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ChildStdout {
|
||||
|
@ -109,6 +117,10 @@ impl AsInner<AnonPipe> for ChildStdout {
|
|||
fn as_inner(&self) -> &AnonPipe { &self.inner }
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for ChildStdout {
|
||||
fn into_inner(self) -> AnonPipe { self.inner }
|
||||
}
|
||||
|
||||
/// A handle to a child procesess's stderr
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ChildStderr {
|
||||
|
@ -126,6 +138,10 @@ impl AsInner<AnonPipe> for ChildStderr {
|
|||
fn as_inner(&self) -> &AnonPipe { &self.inner }
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for ChildStderr {
|
||||
fn into_inner(self) -> AnonPipe { self.inner }
|
||||
}
|
||||
|
||||
/// The `Command` type acts as a process builder, providing fine-grained control
|
||||
/// over how a new process should be spawned. A default configuration can be
|
||||
/// generated using `Command::new(program)`, where `program` gives a path to the
|
||||
|
|
|
@ -184,6 +184,8 @@ impl TcpStream {
|
|||
|
||||
pub fn socket(&self) -> &Socket { &self.inner }
|
||||
|
||||
pub fn into_socket(self) -> Socket { self.inner }
|
||||
|
||||
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||
setsockopt(&self.inner, libc::IPPROTO_TCP, libc::TCP_NODELAY,
|
||||
nodelay as c_int)
|
||||
|
@ -336,6 +338,8 @@ impl TcpListener {
|
|||
|
||||
pub fn socket(&self) -> &Socket { &self.inner }
|
||||
|
||||
pub fn into_socket(self) -> Socket { self.inner }
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe {
|
||||
libc::getsockname(*self.inner.as_inner(), buf, len)
|
||||
|
@ -396,6 +400,8 @@ impl UdpSocket {
|
|||
|
||||
pub fn socket(&self) -> &Socket { &self.inner }
|
||||
|
||||
pub fn into_socket(self) -> Socket { self.inner }
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe {
|
||||
libc::getsockname(*self.inner.as_inner(), buf, len)
|
||||
|
|
|
@ -16,7 +16,7 @@ use fs;
|
|||
use net;
|
||||
use os::raw;
|
||||
use sys;
|
||||
use sys_common::{self, AsInner, FromInner};
|
||||
use sys_common::{self, AsInner, FromInner, IntoInner};
|
||||
|
||||
/// Raw file descriptors.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -59,6 +59,18 @@ pub trait FromRawFd {
|
|||
unsafe fn from_raw_fd(fd: RawFd) -> Self;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to consume an object and acquire ownership of
|
||||
/// its raw file descriptor.
|
||||
#[unstable(feature = "into_raw_os", reason = "recently added API")]
|
||||
pub trait IntoRawFd {
|
||||
/// Consumes this object, returning the raw underlying file descriptor.
|
||||
///
|
||||
/// This function **transfers ownership** of the underlying file descriptor
|
||||
/// to the caller. Callers are then the unique owners of the file descriptor
|
||||
/// and must close the descriptor once it's no longer needed.
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for fs::File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
|
@ -71,6 +83,11 @@ impl FromRawFd for fs::File {
|
|||
fs::File::from_inner(sys::fs::File::from_inner(fd))
|
||||
}
|
||||
}
|
||||
impl IntoRawFd for fs::File {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawFd for net::TcpStream {
|
||||
|
@ -106,3 +123,19 @@ impl FromRawFd for net::UdpSocket {
|
|||
net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for net::TcpStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
}
|
||||
}
|
||||
impl IntoRawFd for net::TcpListener {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
}
|
||||
}
|
||||
impl IntoRawFd for net::UdpSocket {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use os::unix::raw::{uid_t, gid_t};
|
||||
use os::unix::io::{FromRawFd, RawFd, AsRawFd};
|
||||
use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
|
||||
use prelude::v1::*;
|
||||
use process;
|
||||
use sys;
|
||||
use sys_common::{AsInnerMut, AsInner, FromInner};
|
||||
use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
|
||||
|
||||
/// Unix-specific extensions to the `std::process::Command` builder
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -92,3 +92,21 @@ impl AsRawFd for process::ChildStderr {
|
|||
self.as_inner().fd().raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for process::ChildStdin {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for process::ChildStdout {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for process::ChildStderr {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,6 +331,8 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn fd(&self) -> &FileDesc { &self.0 }
|
||||
|
||||
pub fn into_fd(self) -> FileDesc { self.0 }
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
|
|
|
@ -17,7 +17,7 @@ use str;
|
|||
use sys::c;
|
||||
use net::SocketAddr;
|
||||
use sys::fd::FileDesc;
|
||||
use sys_common::{AsInner, FromInner};
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
use sys_common::net::{getsockopt, setsockopt};
|
||||
use time::Duration;
|
||||
|
||||
|
@ -127,3 +127,7 @@ impl AsInner<c_int> for Socket {
|
|||
impl FromInner<c_int> for Socket {
|
||||
fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) }
|
||||
}
|
||||
|
||||
impl IntoInner<c_int> for Socket {
|
||||
fn into_inner(self) -> c_int { self.0.into_raw() }
|
||||
}
|
||||
|
|
|
@ -46,4 +46,5 @@ impl AnonPipe {
|
|||
|
||||
pub fn raw(&self) -> libc::c_int { self.0.raw() }
|
||||
pub fn fd(&self) -> &FileDesc { &self.0 }
|
||||
pub fn into_fd(self) -> FileDesc { self.0 }
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
use fs;
|
||||
use os::windows::raw;
|
||||
use net;
|
||||
use sys_common::{self, AsInner, FromInner};
|
||||
use sys_common::{self, AsInner, FromInner, IntoInner};
|
||||
use sys;
|
||||
|
||||
/// Raw HANDLEs.
|
||||
|
@ -50,6 +50,18 @@ pub trait FromRawHandle {
|
|||
unsafe fn from_raw_handle(handle: RawHandle) -> Self;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to consume an object and acquire ownership of
|
||||
/// its raw `HANDLE`.
|
||||
#[unstable(feature = "into_raw_os", reason = "recently added API")]
|
||||
pub trait IntoRawHandle {
|
||||
/// Consumes this object, returning the raw underlying handle.
|
||||
///
|
||||
/// This function **transfers ownership** of the underlying handle to the
|
||||
/// caller. Callers are then the unique owners of the handle and must close
|
||||
/// it once it's no longer needed.
|
||||
fn into_raw_handle(self) -> RawHandle;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawHandle for fs::File {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
|
@ -65,6 +77,12 @@ impl FromRawHandle for fs::File {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for fs::File {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract raw sockets.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawSocket {
|
||||
|
@ -90,6 +108,18 @@ pub trait FromRawSocket {
|
|||
unsafe fn from_raw_socket(sock: RawSocket) -> Self;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to consume an object and acquire ownership of
|
||||
/// its raw `SOCKET`.
|
||||
#[unstable(feature = "into_raw_os", reason = "recently added API")]
|
||||
pub trait IntoRawSocket {
|
||||
/// Consumes this object, returning the raw underlying socket.
|
||||
///
|
||||
/// This function **transfers ownership** of the underlying socket to the
|
||||
/// caller. Callers are then the unique owners of the socket and must close
|
||||
/// it once it's no longer needed.
|
||||
fn into_raw_socket(self) -> RawSocket;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::TcpStream {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
|
@ -130,3 +160,21 @@ impl FromRawSocket for net::UdpSocket {
|
|||
net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawSocket for net::TcpStream {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawSocket for net::TcpListener {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawSocket for net::UdpSocket {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
|
||||
#![stable(feature = "process_extensions", since = "1.2.0")]
|
||||
|
||||
use os::windows::io::{FromRawHandle, RawHandle, AsRawHandle};
|
||||
use os::windows::io::{FromRawHandle, RawHandle, AsRawHandle, IntoRawHandle};
|
||||
use process;
|
||||
use sys;
|
||||
use sys_common::{AsInner, FromInner};
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||
impl FromRawHandle for process::Stdio {
|
||||
|
@ -32,6 +32,12 @@ impl AsRawHandle for process::Child {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for process::Child {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||
impl AsRawHandle for process::ChildStdin {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
|
@ -52,3 +58,21 @@ impl AsRawHandle for process::ChildStderr {
|
|||
self.as_inner().handle().raw() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for process::ChildStdin {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for process::ChildStdout {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for process::ChildStderr {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
}
|
||||
}
|
||||
|
|
|
@ -319,6 +319,8 @@ impl File {
|
|||
|
||||
pub fn handle(&self) -> &Handle { &self.handle }
|
||||
|
||||
pub fn into_handle(self) -> Handle { self.handle }
|
||||
|
||||
fn reparse_point<'a>(&self,
|
||||
space: &'a mut [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE])
|
||||
-> io::Result<(libc::DWORD, &'a c::REPARSE_DATA_BUFFER)> {
|
||||
|
@ -357,8 +359,6 @@ impl File {
|
|||
Ok(PathBuf::from(OsString::from_wide(subst)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_handle(self) -> Handle { self.handle }
|
||||
}
|
||||
|
||||
impl FromInner<libc::HANDLE> for File {
|
||||
|
|
|
@ -21,7 +21,7 @@ use rt;
|
|||
use sync::Once;
|
||||
use sys;
|
||||
use sys::c;
|
||||
use sys_common::{AsInner, FromInner};
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
use sys_common::net::{setsockopt, getsockopt};
|
||||
use time::Duration;
|
||||
|
||||
|
@ -184,3 +184,11 @@ impl AsInner<libc::SOCKET> for Socket {
|
|||
impl FromInner<libc::SOCKET> for Socket {
|
||||
fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) }
|
||||
}
|
||||
|
||||
impl IntoInner<libc::SOCKET> for Socket {
|
||||
fn into_inner(self) -> libc::SOCKET {
|
||||
let ret = self.0;
|
||||
mem::forget(self);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
|||
|
||||
impl AnonPipe {
|
||||
pub fn handle(&self) -> &Handle { &self.inner }
|
||||
pub fn into_handle(self) -> Handle { self.inner }
|
||||
|
||||
pub fn raw(&self) -> libc::HANDLE { self.inner.raw() }
|
||||
|
||||
|
|
|
@ -220,6 +220,8 @@ impl Process {
|
|||
}
|
||||
|
||||
pub fn handle(&self) -> &Handle { &self.handle }
|
||||
|
||||
pub fn into_handle(self) -> Handle { self.handle }
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
|
|
Loading…
Reference in a new issue