1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
use std::io; use std::mem; use std::os::unix::io::{RawFd}; use nix::unistd::pipe2; use nix::fcntl::O_CLOEXEC; use libc; use libc::{c_void, size_t}; use error::{result, Error}; use error::ErrorCode::CreatePipe; #[derive(Debug)] pub struct Pipe(RawFd, RawFd); #[derive(Debug)] pub struct PipeReader(RawFd); #[derive(Debug)] pub struct PipeWriter(RawFd); #[derive(Debug)] pub enum PipeHolder { Reader(PipeReader), Writer(PipeWriter), } impl Pipe { pub fn new() -> Result<Pipe, Error> { let (rd, wr) = try!(result(CreatePipe, pipe2(O_CLOEXEC))); Ok(Pipe(rd, wr)) } pub fn split(self) -> (PipeReader, PipeWriter) { let Pipe(rd, wr) = self; mem::forget(self); (PipeReader(rd), PipeWriter(wr)) } } impl Drop for Pipe { fn drop(&mut self) { let Pipe(x, y) = *self; unsafe { libc::close(x); libc::close(y); } } } impl PipeReader { pub fn into_fd(self) -> RawFd { let PipeReader(fd) = self; mem::forget(self); return fd; } } impl PipeWriter { pub fn into_fd(self) -> RawFd { let PipeWriter(fd) = self; mem::forget(self); return fd; } } impl Drop for PipeReader { fn drop(&mut self) { unsafe { libc::close(self.0) }; } } impl Drop for PipeWriter { fn drop(&mut self) { unsafe { libc::close(self.0) }; } } impl io::Read for PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { let ret = unsafe { libc::read(self.0, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) }; if ret < 0 { return Err(io::Error::last_os_error()); } Ok(ret as usize) } } impl io::Write for PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { let ret = unsafe { libc::write(self.0, buf.as_ptr() as *const c_void, buf.len() as size_t) }; if ret < 0 { return Err(io::Error::last_os_error()); } Ok(ret as usize) } fn flush(&mut self) -> io::Result<()> { Ok(()) } }