1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Synchronous, in-memory pipes.
13 //! Currently these aren't particularly useful, there only exists bindings
14 //! enough so that pipes can be created to child processes.
16 #![allow(missing_doc)]
20 use io::{IoResult, IoError};
24 use rt::rtio::{RtioPipe, LocalIo};
26 /// A synchronous, in-memory pipe.
27 pub struct PipeStream {
28 /// The internal, opaque runtime pipe object.
29 obj: Box<RtioPipe + Send>,
33 pub reader: PipeStream,
34 pub writer: PipeStream,
38 /// Consumes a file descriptor to return a pipe stream that will have
39 /// synchronous, but non-blocking reads/writes. This is useful if the file
40 /// descriptor is acquired via means other than the standard methods.
42 /// This operation consumes ownership of the file descriptor and it will be
43 /// closed once the object is deallocated.
48 /// # #![allow(unused_must_use)]
49 /// extern crate libc;
51 /// use std::io::pipe::PipeStream;
54 /// let mut pipe = PipeStream::open(libc::STDERR_FILENO);
55 /// pipe.write(b"Hello, stderr!");
58 pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
59 LocalIo::maybe_raise(|io| {
60 io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
61 }).map_err(IoError::from_rtio_error)
65 pub fn new(inner: Box<RtioPipe + Send>) -> PipeStream {
66 PipeStream { obj: inner }
69 /// Creates a pair of in-memory OS pipes for a unidirectional communication
72 /// The structure returned contains a reader and writer I/O object. Data
73 /// written to the writer can be read from the reader.
77 /// This function can fail to succeed if the underlying OS has run out of
78 /// available resources to allocate a new pipe.
79 pub fn pair() -> IoResult<PipePair> {
80 struct Closer { fd: libc::c_int }
82 let os::Pipe { reader, writer } = try!(unsafe { os::pipe() });
83 let mut reader = Closer { fd: reader };
84 let mut writer = Closer { fd: writer };
86 let io_reader = try!(PipeStream::open(reader.fd));
88 let io_writer = try!(PipeStream::open(writer.fd));
90 return Ok(PipePair { reader: io_reader, writer: io_writer });
92 impl Drop for Closer {
95 let _ = unsafe { libc::close(self.fd) };
102 impl Clone for PipeStream {
103 fn clone(&self) -> PipeStream {
104 PipeStream { obj: self.obj.clone() }
108 impl Reader for PipeStream {
109 fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
110 self.obj.read(buf).map_err(IoError::from_rtio_error)
114 impl Writer for PipeStream {
115 fn write(&mut self, buf: &[u8]) -> IoResult<()> {
116 self.obj.write(buf).map_err(IoError::from_rtio_error)
122 iotest!(fn partial_read() {
124 use io::pipe::PipeStream;
126 let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
127 let out = PipeStream::open(writer);
128 let mut input = PipeStream::open(reader);
129 let (tx, rx) = channel();
132 out.write([10]).unwrap();
133 rx.recv(); // don't close the pipe until the other read has finished
136 let mut buf = [0, ..10];
137 input.read(buf).unwrap();