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:
bors 2015-07-20 18:12:40 +00:00
commit 47265bbf37
16 changed files with 195 additions and 15 deletions

View file

@ -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 {

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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()
}
}

View file

@ -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()
}
}

View file

@ -331,6 +331,8 @@ impl File {
}
pub fn fd(&self) -> &FileDesc { &self.0 }
pub fn into_fd(self) -> FileDesc { self.0 }
}
impl DirBuilder {

View file

@ -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() }
}

View file

@ -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 }
}

View file

@ -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()
}
}

View file

@ -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 _
}
}

View file

@ -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 {

View 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
}
}

View file

@ -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() }

View file

@ -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)]