Struct grep_cli::DecompressionReader
source · pub struct DecompressionReader { /* private fields */ }
Expand description
A streaming reader for decompressing the contents of a file.
The purpose of this reader is to provide a seamless way to decompress the
contents of file using existing tools in the current environment. This is
meant to be an alternative to using decompression libraries in favor of the
simplicity and portability of using external commands such as gzip
and
xz
. This does impose the overhead of spawning a process, so other means
for performing decompression should be sought if this overhead isn’t
acceptable.
A decompression reader comes with a default set of matching rules that are
meant to associate file paths with the corresponding command to use to
decompress them. For example, a glob like *.gz
matches gzip compressed
files with the command gzip -d -c
. If a file path does not match any
existing rules, or if it matches a rule whose command does not exist in the
current environment, then the decompression reader passes through the
contents of the underlying file without doing any decompression.
The default matching rules are probably good enough for most cases, and if
they require revision, pull requests are welcome. In cases where they must
be changed or extended, they can be customized through the use of
DecompressionMatcherBuilder
and DecompressionReaderBuilder
.
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 read the decompressed contents of a file without needing to explicitly choose the decompression command to run.
Note that if you need to decompress multiple files, it is better to use
DecompressionReaderBuilder
, which will amortize the cost of compiling the
matcher.
use std::{io::Read, process::Command};
use grep_cli::DecompressionReader;
let mut rdr = DecompressionReader::new("/usr/share/man/man1/ls.1.gz")?;
let mut contents = vec![];
rdr.read_to_end(&mut contents)?;
Implementations§
source§impl DecompressionReader
impl DecompressionReader
sourcepub fn new<P: AsRef<Path>>(path: P) -> Result<DecompressionReader, CommandError>
pub fn new<P: AsRef<Path>>(path: P) -> Result<DecompressionReader, CommandError>
Build a new streaming reader for decompressing data.
If decompression is done out-of-process and if there was a problem spawning the process, then its error is returned.
If the given file path could not be matched with a decompression strategy, then a passthru reader is returned that does no decompression.
This uses the default matching rules for determining how to decompress
the given file. To change those matching rules, use
DecompressionReaderBuilder
and DecompressionMatcherBuilder
.
When creating readers for many paths. it is better to use the builder since it will amortize the cost of constructing the matcher.
sourcepub fn close(&mut self) -> Result<()>
pub fn close(&mut self) -> Result<()>
Closes this reader, freeing any resources used by its underlying child process, if one was used. 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 DecompressionReader
impl Debug for DecompressionReader
source§impl Read for DecompressionReader
impl Read for DecompressionReader
source§fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
1.36.0 · source§fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
read
, except that it reads into a slice of buffers. Read moresource§fn is_read_vectored(&self) -> bool
fn is_read_vectored(&self) -> bool
can_vector
)1.0.0 · source§fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
buf
. Read more1.0.0 · source§fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
buf
. Read more1.6.0 · source§fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
buf
. Read moresource§fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)source§fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)cursor
. Read more1.0.0 · source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Read
. Read more