Skip to content

Commit

Permalink
std: Add IntoRaw{Fd,Handle,Socket} traits
Browse files Browse the repository at this point in the history
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 rust-lang#27062
  • Loading branch information
alexcrichton committed Jul 20, 2015
1 parent 4e51763 commit 7e9e389
Show file tree
Hide file tree
Showing 16 changed files with 195 additions and 15 deletions.
7 changes: 6 additions & 1 deletion src/libstd/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 10 additions & 2 deletions src/libstd/net/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion src/libstd/net/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 17 additions & 1 deletion src/libstd/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/libstd/sys/common/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
35 changes: 34 additions & 1 deletion src/libstd/sys/unix/ext/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
}
}
22 changes: 20 additions & 2 deletions src/libstd/sys/unix/ext/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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()
}
}
2 changes: 2 additions & 0 deletions src/libstd/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@ impl File {
}

pub fn fd(&self) -> &FileDesc { &self.0 }

pub fn into_fd(self) -> FileDesc { self.0 }
}

impl DirBuilder {
Expand Down
6 changes: 5 additions & 1 deletion src/libstd/sys/unix/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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() }
}
1 change: 1 addition & 0 deletions src/libstd/sys/unix/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
50 changes: 49 additions & 1 deletion src/libstd/sys/windows/ext/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
}
}
Loading

0 comments on commit 7e9e389

Please sign in to comment.