]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/pipe.rs
11bb27573c29afece830187f28e270c62c839a28
[rust.git] / src / libstd / io / pipe.rs
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.
4 //
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.
10
11 //! Synchronous, in-memory pipes.
12 //!
13 //! Currently these aren't particularly useful, there only exists bindings
14 //! enough so that pipes can be created to child processes.
15
16 #![allow(missing_doc)]
17
18 use prelude::*;
19 use io::{IoResult, IoError};
20 use libc;
21 use owned::Box;
22 use rt::rtio::{RtioPipe, LocalIo};
23
24 /// A synchronous, in-memory pipe.
25 pub struct PipeStream {
26     /// The internal, opaque runtime pipe object.
27     obj: Box<RtioPipe:Send>,
28 }
29
30 impl PipeStream {
31     /// Consumes a file descriptor to return a pipe stream that will have
32     /// synchronous, but non-blocking reads/writes. This is useful if the file
33     /// descriptor is acquired via means other than the standard methods.
34     ///
35     /// This operation consumes ownership of the file descriptor and it will be
36     /// closed once the object is deallocated.
37     ///
38     /// # Example
39     ///
40     /// ```rust
41     /// # #![allow(unused_must_use)]
42     /// extern crate libc;
43     ///
44     /// use std::io::pipe::PipeStream;
45     ///
46     /// fn main() {
47     ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
48     ///     pipe.write(bytes!("Hello, stderr!"));
49     /// }
50     /// ```
51     pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
52         LocalIo::maybe_raise(|io| {
53             io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
54         }).map_err(IoError::from_rtio_error)
55     }
56
57     #[doc(hidden)]
58     pub fn new(inner: Box<RtioPipe:Send>) -> PipeStream {
59         PipeStream { obj: inner }
60     }
61 }
62
63 impl Clone for PipeStream {
64     fn clone(&self) -> PipeStream {
65         PipeStream { obj: self.obj.clone() }
66     }
67 }
68
69 impl Reader for PipeStream {
70     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
71         self.obj.read(buf).map_err(IoError::from_rtio_error)
72     }
73 }
74
75 impl Writer for PipeStream {
76     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
77         self.obj.write(buf).map_err(IoError::from_rtio_error)
78     }
79 }
80
81 #[cfg(test)]
82 mod test {
83     iotest!(fn partial_read() {
84         use os;
85         use io::pipe::PipeStream;
86
87         let os::Pipe { input, out } = os::pipe();
88         let out = PipeStream::open(out);
89         let mut input = PipeStream::open(input);
90         let (tx, rx) = channel();
91         spawn(proc() {
92             let mut out = out;
93             out.write([10]).unwrap();
94             rx.recv(); // don't close the pipe until the other read has finished
95         });
96
97         let mut buf = [0, ..10];
98         input.read(buf).unwrap();
99         tx.send(());
100     })
101 }