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
mod end_reader;
mod end_writer;
pub(crate) use end_reader::EndReader;
pub(crate) use end_writer::EndWriter;
use std::fs::File;
use std::io::{PipeReader, PipeWriter, pipe};
use std::os::fd::OwnedFd;
use crate::error::*;
/// Describes what to do with a standard I/O stream.
#[derive(Debug)]
pub enum Stdio {
Inherit,
MakePipe,
Fd(OwnedFd),
}
impl Stdio {
/// The child inherits from the corresponding parent descriptor.
pub fn inherit() -> Self {
Self::Inherit
}
/// A new pipe should be arranged to connect the parent and child processes.
pub fn piped() -> Self {
Self::MakePipe
}
/// Converts the given instance into the ends of the pipe it represents. `for_output` should
/// be set to `true` for instances which represent stdout & stderr pipes.
///
/// - [Inherit](Stdio::Inherit) returns two None values.
/// - [MakePipe](Stdio::MakePipe) returns [EndReader::Pipe] & [EndWriter::Pipe].
/// - [Fd](Stdio::Fd) returns [EndReader::Fd] & None if for_output is false
/// - [Fd](Stdio::Fd) returns None & [EndWriter::Fd] if for_output is true
///
pub(crate) fn into_ends(
io: Self,
for_output: bool,
) -> Result<(Option<EndReader>, Option<EndWriter>)> {
Ok(match (io, for_output) {
(Self::Inherit, _) => (None, None),
(Self::MakePipe, _) => {
let pipe = pipe().map_err(ProcessErrorKind::StdIoError)?;
(Some(EndReader::Pipe(pipe.0)), Some(EndWriter::Pipe(pipe.1)))
}
(Self::Fd(fd), false) => (Some(EndReader::Fd(fd)), None),
(Self::Fd(fd), true) => (None, Some(EndWriter::Fd(fd))),
})
}
}
impl From<File> for Stdio {
/// Converts a [File] into a [Stdio].
fn from(fd: File) -> Self {
Self::Fd(fd.into())
}
}
impl From<OwnedFd> for Stdio {
/// Takes ownership of a file descriptor and returns a [Stdio] that can attach a stream to it.
fn from(fd: OwnedFd) -> Self {
Self::Fd(fd)
}
}
impl From<PipeReader> for Stdio {
fn from(pipe: PipeReader) -> Self {
Self::Fd(pipe.into())
}
}
impl From<PipeWriter> for Stdio {
fn from(pipe: PipeWriter) -> Self {
Self::Fd(pipe.into())
}
}