Struct grep_cli::CommandReader

source ·
pub struct CommandReader { /* private fields */ }
Expand description

A streaming reader for a command’s output.

The purpose of this reader is to provide an easy way to execute processes whose stdout is read in a streaming way while also making the processes’ stderr available when the process fails with an exit code. This makes it possible to execute processes while surfacing the underlying failure mode in the case of an error.

Moreover, by default, this reader will asynchronously read the processes’ stderr. This prevents subtle deadlocking bugs for noisy processes that write a lot to stderr. Currently, the entire contents of stderr is read on to the heap.

§Example

This example shows how to invoke gzip to decompress the contents of a file. If the gzip command reports a failing exit status, then its stderr is returned as an error.

use std::{io::Read, process::Command};

use grep_cli::CommandReader;

let mut cmd = Command::new("gzip");
cmd.arg("-d").arg("-c").arg("/usr/share/man/man1/ls.1.gz");

let mut rdr = CommandReader::new(&mut cmd)?;
let mut contents = vec![];
rdr.read_to_end(&mut contents)?;

Implementations§

source§

impl CommandReader

source

pub fn new(cmd: &mut Command) -> Result<CommandReader, CommandError>

Create a new streaming reader for the given command using the default configuration.

The caller should set everything that’s required on the given command before building a reader, such as its arguments, environment and current working directory. Settings such as the stdout and stderr (but not stdin) pipes will be overridden so that they can be controlled by the reader.

If there was a problem spawning the given command, then its error is returned.

If the caller requires additional configuration for the reader returned, then use CommandReaderBuilder.

source

pub fn close(&mut self) -> Result<()>

Closes the CommandReader, freeing any resources used by its underlying child process. If the child process exits with a nonzero exit code, the returned Err value will include its stderr.

close is idempotent, meaning it can be safely called multiple times. The first call closes the CommandReader and any subsequent calls do nothing.

This method should be called after partially reading a file to prevent resource leakage. However there is no need to call close explicitly if your code always calls read to EOF, as read takes care of calling close in this case.

close is also called in drop as a last line of defense against resource leakage. Any error from the child process is then printed as a warning to stderr. This can be avoided by explicitly calling close before the CommandReader is dropped.

Trait Implementations§

source§

impl Debug for CommandReader

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for CommandReader

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl Read for CommandReader

source§

fn read(&mut self, buf: &mut [u8]) -> Result<usize>

Pull some bytes from this source into the specified buffer, returning how many bytes were read. Read more
1.36.0 · source§

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>

Like read, except that it reads into a slice of buffers. Read more
source§

fn is_read_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Reader has an efficient read_vectored implementation. Read more
1.0.0 · source§

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>

Reads all bytes until EOF in this source, placing them into buf. Read more
1.0.0 · source§

fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>

Reads all bytes until EOF in this source, appending them to buf. Read more
1.6.0 · source§

fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>

Reads the exact number of bytes required to fill buf. Read more
source§

fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>

🔬This is a nightly-only experimental API. (read_buf)
Pull some bytes from this source into the specified buffer. Read more
source§

fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>

🔬This is a nightly-only experimental API. (read_buf)
Reads the exact number of bytes required to fill cursor. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Self
where Self: Sized,

Creates a “by reference” adaptor for this instance of Read. Read more
1.0.0 · source§

fn bytes(self) -> Bytes<Self>
where Self: Sized,

Transforms this Read instance to an Iterator over its bytes. Read more
1.0.0 · source§

fn chain<R>(self, next: R) -> Chain<Self, R>
where R: Read, Self: Sized,

Creates an adapter which will chain this stream with another. Read more
1.0.0 · source§

fn take(self, limit: u64) -> Take<Self>
where Self: Sized,

Creates an adapter which will read at most limit bytes from it. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.