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

source

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.

source

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

source§

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

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

impl Read for DecompressionReader

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, Global>) -> Result<usize, Error>

Read 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>

Read 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>

Read 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)
Read the exact number of bytes required to fill cursor. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Selfwhere 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 Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere 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 Twhere 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 Twhere U: Into<T>,

§

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 Twhere U: TryFrom<T>,

§

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.