summaryrefslogtreecommitdiffstats
path: root/vendor/flate2/src/gz
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/flate2/src/gz')
-rw-r--r--vendor/flate2/src/gz/bufread.rs18
-rw-r--r--vendor/flate2/src/gz/mod.rs10
-rw-r--r--vendor/flate2/src/gz/read.rs4
-rw-r--r--vendor/flate2/src/gz/write.rs136
4 files changed, 148 insertions, 20 deletions
diff --git a/vendor/flate2/src/gz/bufread.rs b/vendor/flate2/src/gz/bufread.rs
index 6be144d0c..c6ac5a98b 100644
--- a/vendor/flate2/src/gz/bufread.rs
+++ b/vendor/flate2/src/gz/bufread.rs
@@ -74,7 +74,7 @@ fn read_gz_header_part<'a, R: Read>(r: &'a mut Buffer<'a, R>) -> io::Result<()>
}
GzHeaderParsingState::Filename => {
if r.part.flg & FNAME != 0 {
- if None == r.part.header.filename {
+ if r.part.header.filename.is_none() {
r.part.header.filename = Some(Vec::new());
};
for byte in r.bytes() {
@@ -88,7 +88,7 @@ fn read_gz_header_part<'a, R: Read>(r: &'a mut Buffer<'a, R>) -> io::Result<()>
}
GzHeaderParsingState::Comment => {
if r.part.flg & FCOMMENT != 0 {
- if None == r.part.header.comment {
+ if r.part.header.comment.is_none() {
r.part.header.comment = Some(Vec::new());
};
for byte in r.bytes() {
@@ -483,7 +483,7 @@ impl<R> GzDecoder<R> {
/// Acquires a mutable reference to the underlying stream.
///
/// Note that mutation of the stream may result in surprising results if
- /// this encoder is continued to be used.
+ /// this decoder is continued to be used.
pub fn get_mut(&mut self) -> &mut R {
self.reader.get_mut().get_mut()
}
@@ -681,7 +681,7 @@ impl<R> MultiGzDecoder<R> {
/// Acquires a mutable reference to the underlying stream.
///
/// Note that mutation of the stream may result in surprising results if
- /// this encoder is continued to be used.
+ /// this decoder is continued to be used.
pub fn get_mut(&mut self) -> &mut R {
self.0.get_mut()
}
@@ -718,20 +718,20 @@ pub mod tests {
}
pub fn set_position(&mut self, pos: u64) {
- return self.cursor.set_position(pos);
+ self.cursor.set_position(pos)
}
pub fn position(&mut self) -> u64 {
- return self.cursor.position();
+ self.cursor.position()
}
}
impl Write for BlockingCursor {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- return self.cursor.write(buf);
+ self.cursor.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
- return self.cursor.flush();
+ self.cursor.flush()
}
}
@@ -751,7 +751,7 @@ pub mod tests {
}
Ok(_n) => {}
}
- return r;
+ r
}
}
#[test]
diff --git a/vendor/flate2/src/gz/mod.rs b/vendor/flate2/src/gz/mod.rs
index 505450e3e..d31aa60be 100644
--- a/vendor/flate2/src/gz/mod.rs
+++ b/vendor/flate2/src/gz/mod.rs
@@ -218,11 +218,11 @@ impl GzBuilder {
}
if let Some(filename) = filename {
flg |= FNAME;
- header.extend(filename.as_bytes_with_nul().iter().map(|x| *x));
+ header.extend(filename.as_bytes_with_nul().iter().copied());
}
if let Some(comment) = comment {
flg |= FCOMMENT;
- header.extend(comment.as_bytes_with_nul().iter().map(|x| *x));
+ header.extend(comment.as_bytes_with_nul().iter().copied());
}
header[0] = 0x1f;
header[1] = 0x8b;
@@ -285,14 +285,14 @@ mod tests {
let v = crate::random_bytes().take(1024).collect::<Vec<_>>();
for _ in 0..200 {
let to_write = &v[..thread_rng().gen_range(0..v.len())];
- real.extend(to_write.iter().map(|x| *x));
+ real.extend(to_write.iter().copied());
w.write_all(to_write).unwrap();
}
let result = w.finish().unwrap();
let mut r = read::GzDecoder::new(&result[..]);
let mut v = Vec::new();
r.read_to_end(&mut v).unwrap();
- assert!(v == real);
+ assert_eq!(v, real);
}
#[test]
@@ -301,7 +301,7 @@ mod tests {
let mut r = read::GzDecoder::new(read::GzEncoder::new(&v[..], Compression::default()));
let mut res = Vec::new();
r.read_to_end(&mut res).unwrap();
- assert!(res == v);
+ assert_eq!(res, v);
}
#[test]
diff --git a/vendor/flate2/src/gz/read.rs b/vendor/flate2/src/gz/read.rs
index dbbe63282..cfeb992e8 100644
--- a/vendor/flate2/src/gz/read.rs
+++ b/vendor/flate2/src/gz/read.rs
@@ -153,7 +153,7 @@ impl<R> GzDecoder<R> {
/// Acquires a mutable reference to the underlying stream.
///
/// Note that mutation of the stream may result in surprising results if
- /// this encoder is continued to be used.
+ /// this decoder is continued to be used.
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
@@ -250,7 +250,7 @@ impl<R> MultiGzDecoder<R> {
/// Acquires a mutable reference to the underlying stream.
///
/// Note that mutation of the stream may result in surprising results if
- /// this encoder is continued to be used.
+ /// this decoder is continued to be used.
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
diff --git a/vendor/flate2/src/gz/write.rs b/vendor/flate2/src/gz/write.rs
index 7cf1a7cd4..83eebb757 100644
--- a/vendor/flate2/src/gz/write.rs
+++ b/vendor/flate2/src/gz/write.rs
@@ -92,7 +92,7 @@ impl<W: Write> GzEncoder<W> {
self.inner.finish()?;
while self.crc_bytes_written < 8 {
- let (sum, amt) = (self.crc.sum() as u32, self.crc.amount());
+ let (sum, amt) = (self.crc.sum(), self.crc.amount());
let buf = [
(sum >> 0) as u8,
(sum >> 8) as u8,
@@ -169,7 +169,7 @@ impl<W: Write> Drop for GzEncoder<W> {
/// A gzip streaming decoder
///
-/// This structure exposes a [`Write`] interface that will emit compressed data
+/// This structure exposes a [`Write`] interface that will emit uncompressed data
/// to the underlying writer `W`.
///
/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
@@ -296,7 +296,7 @@ impl<W: Write> GzDecoder<W> {
| ((self.crc_bytes[5] as u32) << 8)
| ((self.crc_bytes[6] as u32) << 16)
| ((self.crc_bytes[7] as u32) << 24);
- if crc != self.inner.get_ref().crc().sum() as u32 {
+ if crc != self.inner.get_ref().crc().sum() {
return Err(corrupt());
}
if amt != self.inner.get_ref().crc().amount() {
@@ -373,11 +373,117 @@ impl<W: Read + Write> Read for GzDecoder<W> {
}
}
+/// A gzip streaming decoder that decodes all members of a multistream
+///
+/// A gzip member consists of a header, compressed data and a trailer. The [gzip
+/// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple
+/// gzip members to be joined in a single stream. `MultiGzDecoder` will
+/// decode all consecutive members while `GzDecoder` will only decompress
+/// the first gzip member. The multistream format is commonly used in
+/// bioinformatics, for example when using the BGZF compressed data.
+///
+/// This structure exposes a [`Write`] interface that will consume all gzip members
+/// from the written buffers and write uncompressed data to the writer.
+#[derive(Debug)]
+pub struct MultiGzDecoder<W: Write> {
+ inner: GzDecoder<W>,
+}
+
+impl<W: Write> MultiGzDecoder<W> {
+ /// Creates a new decoder which will write uncompressed data to the stream.
+ /// If the gzip stream contains multiple members all will be decoded.
+ pub fn new(w: W) -> MultiGzDecoder<W> {
+ MultiGzDecoder {
+ inner: GzDecoder::new(w),
+ }
+ }
+
+ /// Returns the header associated with the current member.
+ pub fn header(&self) -> Option<&GzHeader> {
+ self.inner.header()
+ }
+
+ /// Acquires a reference to the underlying writer.
+ pub fn get_ref(&self) -> &W {
+ self.inner.get_ref()
+ }
+
+ /// Acquires a mutable reference to the underlying writer.
+ ///
+ /// Note that mutating the output/input state of the stream may corrupt this
+ /// object, so care must be taken when using this method.
+ pub fn get_mut(&mut self) -> &mut W {
+ self.inner.get_mut()
+ }
+
+ /// Attempt to finish this output stream, writing out final chunks of data.
+ ///
+ /// Note that this function can only be used once data has finished being
+ /// written to the output stream. After this function is called then further
+ /// calls to `write` may result in a panic.
+ ///
+ /// # Panics
+ ///
+ /// Attempts to write data to this stream may result in a panic after this
+ /// function is called.
+ ///
+ /// # Errors
+ ///
+ /// This function will perform I/O to finish the stream, returning any
+ /// errors which happen.
+ pub fn try_finish(&mut self) -> io::Result<()> {
+ self.inner.try_finish()
+ }
+
+ /// Consumes this decoder, flushing the output stream.
+ ///
+ /// This will flush the underlying data stream and then return the contained
+ /// writer if the flush succeeded.
+ ///
+ /// Note that this function may not be suitable to call in a situation where
+ /// the underlying stream is an asynchronous I/O stream. To finish a stream
+ /// the `try_finish` (or `shutdown`) method should be used instead. To
+ /// re-acquire ownership of a stream it is safe to call this method after
+ /// `try_finish` or `shutdown` has returned `Ok`.
+ ///
+ /// # Errors
+ ///
+ /// This function will perform I/O to complete this stream, and any I/O
+ /// errors which occur will be returned from this function.
+ pub fn finish(self) -> io::Result<W> {
+ self.inner.finish()
+ }
+}
+
+impl<W: Write> Write for MultiGzDecoder<W> {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ if buf.is_empty() {
+ Ok(0)
+ } else {
+ match self.inner.write(buf) {
+ Ok(0) => {
+ // When the GzDecoder indicates that it has finished
+ // create a new GzDecoder to handle additional data.
+ self.inner.try_finish()?;
+ let w = self.inner.inner.take_inner().into_inner();
+ self.inner = GzDecoder::new(w);
+ self.inner.write(buf)
+ }
+ res => res,
+ }
+ }
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.inner.flush()
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
- const STR: &'static str = "Hello World Hello World Hello World Hello World Hello World \
+ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
@@ -447,4 +553,26 @@ mod tests {
let return_string = String::from_utf8(writer).expect("String parsing error");
assert_eq!(return_string, STR);
}
+
+ // Two or more gzip files concatenated form a multi-member gzip file. MultiGzDecoder will
+ // concatenate the decoded contents of all members.
+ #[test]
+ fn decode_multi_writer() {
+ let mut e = GzEncoder::new(Vec::new(), Compression::default());
+ e.write(STR.as_ref()).unwrap();
+ let bytes = e.finish().unwrap().repeat(2);
+
+ let mut writer = Vec::new();
+ let mut decoder = MultiGzDecoder::new(writer);
+ let mut count = 0;
+ while count < bytes.len() {
+ let n = decoder.write(&bytes[count..]).unwrap();
+ assert!(n != 0);
+ count += n;
+ }
+ writer = decoder.finish().unwrap();
+ let return_string = String::from_utf8(writer).expect("String parsing error");
+ let expected = STR.repeat(2);
+ assert_eq!(return_string, expected);
+ }
}