summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2018-06-18 19:18:56 +0200
committerJustus Winter <justus@sequoia-pgp.org>2018-06-19 11:41:00 +0200
commitb2ee991c96698043f922b2b2d2dea77436db7549 (patch)
treebec005196021436ce88405ee40323aace72f4747
parentb6f578b052ca4356d787ee428b1b00820e0775ab (diff)
openpgp, buffered-reader: Make compression an optional feature.
- This helps to reduce the trusted computing base if compression is not needed. - This makes it easier to fuzz Sequoia, previously the fuzzer was doing a great job creating compression bombs that triggered the fuzzers timeout. - Currently, the cargo workspace feature does not propagate --no-default-features, but it is possible to depend on the openpgp crate with `default-features = false`. - Unfortunately, a lot of test cases include compressed packages. This change conditionally disables these tests.
-rw-r--r--buffered-reader/Cargo.toml12
-rw-r--r--buffered-reader/src/decompress_bzip2.rs118
-rw-r--r--buffered-reader/src/decompress_deflate.rs (renamed from buffered-reader/src/decompress.rs)112
-rw-r--r--buffered-reader/src/lib.rs16
-rw-r--r--openpgp/Cargo.toml14
-rw-r--r--openpgp/src/lib.rs2
-rw-r--r--openpgp/src/packet_pile.rs9
-rw-r--r--openpgp/src/parse/packet_pile_parser.rs2
-rw-r--r--openpgp/src/parse/parse.rs23
-rw-r--r--openpgp/src/parse/subpacket.rs1
-rw-r--r--openpgp/src/serialize/mod.rs1
-rw-r--r--openpgp/src/serialize/stream.rs4
-rw-r--r--openpgp/src/serialize/writer/mod.rs (renamed from openpgp/src/serialize/writer.rs)195
-rw-r--r--openpgp/src/serialize/writer/writer_bzip2.rs68
-rw-r--r--openpgp/src/serialize/writer/writer_deflate.rs129
-rw-r--r--openpgp/src/signature.rs12
16 files changed, 403 insertions, 315 deletions
diff --git a/buffered-reader/Cargo.toml b/buffered-reader/Cargo.toml
index 68f4c60d..1702ac97 100644
--- a/buffered-reader/Cargo.toml
+++ b/buffered-reader/Cargo.toml
@@ -4,5 +4,13 @@ version = "0.1.0"
authors = ["Neal H. Walfield <neal@gnu.org>"]
[dependencies]
-bzip2 = "0.3.2"
-flate2 = "1.0.1"
+bzip2 = { version = "0.3.2", optional = true }
+flate2 = { version = "1.0.1", optional = true }
+
+[features]
+default = ["compression"]
+
+# The compression algorithms.
+compression = ["compression-deflate", "compression-bzip2"]
+compression-deflate = ["flate2"]
+compression-bzip2 = ["bzip2"]
diff --git a/buffered-reader/src/decompress_bzip2.rs b/buffered-reader/src/decompress_bzip2.rs
new file mode 100644
index 00000000..41fba37a
--- /dev/null
+++ b/buffered-reader/src/decompress_bzip2.rs
@@ -0,0 +1,118 @@
+use std::io;
+use std::fmt;
+
+use bzip2::read::BzDecoder;
+
+use super::*;
+
+
+pub struct BufferedReaderBzip<R: BufferedReader<C>, C> {
+ reader: BufferedReaderGeneric<BzDecoder<R>, C>,
+}
+
+impl <R: BufferedReader<()>> BufferedReaderBzip<R, ()> {
+ /// Instantiate a new bzip decompression reader. `reader` is
+ /// the source to wrap.
+ pub fn new(reader: R) -> Self {
+ Self::with_cookie(reader, ())
+ }
+}
+
+impl <R: BufferedReader<C>, C> BufferedReaderBzip<R, C> {
+ /// Like `new()`, but sets a cookie, which can be retrieved using
+ /// the `cookie_ref` and `cookie_mut` methods, and set using
+ /// the `cookie_set` method.
+ pub fn with_cookie(reader: R, cookie: C) -> Self {
+ BufferedReaderBzip {
+ reader: BufferedReaderGeneric::with_cookie(
+ BzDecoder::new(reader), None, cookie),
+ }
+ }
+}
+
+impl<R: BufferedReader<C>, C> io::Read for BufferedReaderBzip<R, C> {
+ fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
+ self.reader.read(buf)
+ }
+}
+
+impl <R: BufferedReader<C>, C> fmt::Debug for BufferedReaderBzip<R, C> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("BufferedReaderBzip")
+ .field("reader", &self.get_ref().unwrap())
+ .finish()
+ }
+}
+
+impl<R: BufferedReader<C>, C> BufferedReader<C> for BufferedReaderBzip<R, C> {
+ fn buffer(&self) -> &[u8] {
+ return self.reader.buffer();
+ }
+
+ fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
+ return self.reader.data(amount);
+ }
+
+ fn data_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
+ return self.reader.data_hard(amount);
+ }
+
+ fn data_eof(&mut self) -> Result<&[u8], io::Error> {
+ return self.reader.data_eof();
+ }
+
+ fn consume(&mut self, amount: usize) -> &[u8] {
+ return self.reader.consume(amount);
+ }
+
+ fn data_consume(&mut self, amount: usize)
+ -> Result<&[u8], io::Error> {
+ return self.reader.data_consume(amount);
+ }
+
+ fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
+ return self.reader.data_consume_hard(amount);
+ }
+
+ fn read_be_u16(&mut self) -> Result<u16, io::Error> {
+ return self.reader.read_be_u16();
+ }
+
+ fn read_be_u32(&mut self) -> Result<u32, io::Error> {
+ return self.reader.read_be_u32();
+ }
+
+ fn steal(&mut self, amount: usize) -> Result<Vec<u8>, io::Error> {
+ return self.reader.steal(amount);
+ }
+
+ fn steal_eof(&mut self) -> Result<Vec<u8>, io::Error> {
+ return self.reader.steal_eof();
+ }
+
+ fn get_mut(&mut self) -> Option<&mut BufferedReader<C>> {
+ Some(self.reader.reader.get_mut())
+ }
+
+ fn get_ref(&self) -> Option<&BufferedReader<C>> {
+ Some(self.reader.reader.get_ref())
+ }
+
+ fn into_inner<'b>(self: Box<Self>)
+ -> Option<Box<BufferedReader<C> + 'b>> where Self: 'b {
+ // Strip the outer box.
+ Some(Box::new(self.reader.reader.into_inner()))
+ }
+
+ fn cookie_set(&mut self, cookie: C) -> C {
+ self.reader.cookie_set(cookie)
+ }
+
+ fn cookie_ref(&self) -> &C {
+ self.reader.cookie_ref()
+ }
+
+ fn cookie_mut(&mut self) -> &mut C {
+ self.reader.cookie_mut()
+ }
+}
diff --git a/buffered-reader/src/decompress.rs b/buffered-reader/src/decompress_deflate.rs
index 376edd06..c46b9eea 100644
--- a/buffered-reader/src/decompress.rs
+++ b/buffered-reader/src/decompress_deflate.rs
@@ -3,7 +3,6 @@ use std::fmt;
use flate2::read::DeflateDecoder;
use flate2::read::ZlibDecoder;
-use bzip2::read::BzDecoder;
use super::*;
@@ -230,117 +229,6 @@ impl<R: BufferedReader<C>, C> BufferedReader<C>
self.reader.cookie_mut()
}
}
-
-pub struct BufferedReaderBzip<R: BufferedReader<C>, C> {
- reader: BufferedReaderGeneric<BzDecoder<R>, C>,
-}
-
-impl <R: BufferedReader<()>> BufferedReaderBzip<R, ()> {
- /// Instantiate a new bzip decompression reader. `reader` is
- /// the source to wrap.
- pub fn new(reader: R) -> Self {
- Self::with_cookie(reader, ())
- }
-}
-
-impl <R: BufferedReader<C>, C> BufferedReaderBzip<R, C> {
- /// Like `new()`, but sets a cookie, which can be retrieved using
- /// the `cookie_ref` and `cookie_mut` methods, and set using
- /// the `cookie_set` method.
- pub fn with_cookie(reader: R, cookie: C) -> Self {
- BufferedReaderBzip {
- reader: BufferedReaderGeneric::with_cookie(
- BzDecoder::new(reader), None, cookie),
- }
- }
-}
-
-impl<R: BufferedReader<C>, C> io::Read for BufferedReaderBzip<R, C> {
- fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
- self.reader.read(buf)
- }
-}
-
-impl <R: BufferedReader<C>, C> fmt::Debug for BufferedReaderBzip<R, C> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("BufferedReaderBzip")
- .field("reader", &self.get_ref().unwrap())
- .finish()
- }
-}
-
-impl<R: BufferedReader<C>, C> BufferedReader<C> for BufferedReaderBzip<R, C> {
- fn buffer(&self) -> &[u8] {
- return self.reader.buffer();
- }
-
- fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.reader.data(amount);
- }
-
- fn data_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.reader.data_hard(amount);
- }
-
- fn data_eof(&mut self) -> Result<&[u8], io::Error> {
- return self.reader.data_eof();
- }
-
- fn consume(&mut self, amount: usize) -> &[u8] {
- return self.reader.consume(amount);
- }
-
- fn data_consume(&mut self, amount: usize)
- -> Result<&[u8], io::Error> {
- return self.reader.data_consume(amount);
- }
-
- fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.reader.data_consume_hard(amount);
- }
-
- fn read_be_u16(&mut self) -> Result<u16, io::Error> {
- return self.reader.read_be_u16();
- }
-
- fn read_be_u32(&mut self) -> Result<u32, io::Error> {
- return self.reader.read_be_u32();
- }
-
- fn steal(&mut self, amount: usize) -> Result<Vec<u8>, io::Error> {
- return self.reader.steal(amount);
- }
-
- fn steal_eof(&mut self) -> Result<Vec<u8>, io::Error> {
- return self.reader.steal_eof();
- }
-
- fn get_mut(&mut self) -> Option<&mut BufferedReader<C>> {
- Some(self.reader.reader.get_mut())
- }
-
- fn get_ref(&self) -> Option<&BufferedReader<C>> {
- Some(self.reader.reader.get_ref())
- }
-
- fn into_inner<'b>(self: Box<Self>)
- -> Option<Box<BufferedReader<C> + 'b>> where Self: 'b {
- // Strip the outer box.
- Some(Box::new(self.reader.reader.into_inner()))
- }
-
- fn cookie_set(&mut self, cookie: C) -> C {
- self.reader.cookie_set(cookie)
- }
-
- fn cookie_ref(&self) -> &C {
- self.reader.cookie_ref()
- }
-
- fn cookie_mut(&mut self) -> &mut C {
- self.reader.cookie_mut()
- }
-}
#[cfg(test)]
mod test {
diff --git a/buffered-reader/src/lib.rs b/buffered-reader/src/lib.rs
index ab19fa37..9619e0de 100644
--- a/buffered-reader/src/lib.rs
+++ b/buffered-reader/src/lib.rs
@@ -1,6 +1,8 @@
//! An improved `BufRead` interface.
+#[cfg(feature = "compression-deflate")]
extern crate flate2;
+#[cfg(feature = "compression-bzip2")]
extern crate bzip2;
use std::io;
@@ -13,16 +15,22 @@ mod memory;
mod limitor;
mod dup;
mod eof;
-mod decompress;
+#[cfg(feature = "compression-deflate")]
+mod decompress_deflate;
+#[cfg(feature = "compression-bzip2")]
+mod decompress_bzip2;
pub use self::generic::BufferedReaderGeneric;
pub use self::memory::BufferedReaderMemory;
pub use self::limitor::BufferedReaderLimitor;
pub use self::dup::BufferedReaderDup;
pub use self::eof::BufferedReaderEOF;
-pub use self::decompress::BufferedReaderDeflate;
-pub use self::decompress::BufferedReaderZlib;
-pub use self::decompress::BufferedReaderBzip;
+#[cfg(feature = "compression-deflate")]
+pub use self::decompress_deflate::BufferedReaderDeflate;
+#[cfg(feature = "compression-deflate")]
+pub use self::decompress_deflate::BufferedReaderZlib;
+#[cfg(feature = "compression-bzip2")]
+pub use self::decompress_bzip2::BufferedReaderBzip;
// The default buffer size.
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml
index 3d2d4c31..acf33a3c 100644
--- a/openpgp/Cargo.toml
+++ b/openpgp/Cargo.toml
@@ -4,11 +4,19 @@ version = "0.1.0"
authors = ["Neal H. Walfield <neal@gnu.org>"]
[dependencies]
-buffered-reader = { path = "../buffered-reader" }
+buffered-reader = { path = "../buffered-reader", default-features = false }
base64 = "0.9.0"
-bzip2 = "0.3.2"
+bzip2 = { version = "0.3.2", optional = true }
failure = "0.1.1"
-flate2 = "1.0.1"
+flate2 = { version = "1.0.1", optional = true }
nettle = { git = "https://gitlab.com/sequoia-pgp/nettle-rs.git" }
quickcheck = "0.6"
time = "0.1.38"
+
+[features]
+default = ["compression"]
+
+# The compression algorithms.
+compression = ["compression-deflate", "compression-bzip2"]
+compression-deflate = ["flate2", "buffered-reader/compression-deflate"]
+compression-bzip2 = ["bzip2", "buffered-reader/compression-bzip2"]
diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs
index 8bfd504e..af011720 100644
--- a/openpgp/src/lib.rs
+++ b/openpgp/src/lib.rs
@@ -45,7 +45,9 @@ extern crate buffered_reader;
extern crate nettle;
+#[cfg(feature = "compression-deflate")]
extern crate flate2;
+#[cfg(feature = "compression-bzip2")]
extern crate bzip2;
#[cfg(test)]
diff --git a/openpgp/src/packet_pile.rs b/openpgp/src/packet_pile.rs
index 55851fb1..65ca1b79 100644
--- a/openpgp/src/packet_pile.rs
+++ b/openpgp/src/packet_pile.rs
@@ -27,6 +27,7 @@ macro_rules! bytes {
use std::path::PathBuf;
#[cfg(test)]
+#[allow(dead_code)]
fn path_to(artifact: &str) -> PathBuf {
[env!("CARGO_MANIFEST_DIR"), "tests", "data", "messages", artifact]
.iter().collect()
@@ -434,8 +435,6 @@ mod message_test {
use SEIP;
use packet::Tag;
- use std::io::Read;
-
#[test]
fn deserialize_test_1 () {
// XXX: This test should be more thorough. Right now, we mostly
@@ -456,6 +455,7 @@ mod message_test {
assert_eq!(count, 61);
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn deserialize_test_2 () {
// A message containing a compressed packet that contains a
@@ -474,6 +474,7 @@ mod message_test {
assert_eq!(count, 2);
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn deserialize_test_3 () {
let path = path_to("signed.gpg");
@@ -526,6 +527,7 @@ mod message_test {
assert_eq!(pile.children().len(), 77);
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn compression_quine_test_1 () {
// Use the PacketPile::from_file interface to parse an OpenPGP
@@ -547,6 +549,7 @@ mod message_test {
assert_eq!(count, 1 + max_recursion_depth);
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn compression_quine_test_2 () {
// Use the iterator interface to parse an OpenPGP quine.
@@ -577,8 +580,10 @@ mod message_test {
assert_eq!(count, 1 + max_recursion_depth as usize);
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn consume_content_1 () {
+ use std::io::Read;
// A message containing a compressed packet that contains a
// literal packet. When we read some of the compressed
// packet, we expect recurse() to not recurse.
diff --git a/openpgp/src/parse/packet_pile_parser.rs b/openpgp/src/parse/packet_pile_parser.rs
index 3d48a8b0..f19deb81 100644
--- a/openpgp/src/parse/packet_pile_parser.rs
+++ b/openpgp/src/parse/packet_pile_parser.rs
@@ -13,6 +13,7 @@ use buffered_reader::{BufferedReader, BufferedReaderGeneric,
BufferedReaderMemory};
#[cfg(test)]
+#[allow(unused_macros)]
macro_rules! bytes {
( $x:expr ) => { include_bytes!(concat!("../../tests/data/messages/", $x)) };
}
@@ -282,6 +283,7 @@ fn message_parser_test() {
// Check that we can use the read interface to stream the contents of
// a packet.
+#[cfg(feature = "compression-deflate")]
#[test]
fn message_parser_reader_interface() {
use std::io::Read;
diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs
index 1b431b3d..145ace09 100644
--- a/openpgp/src/parse/parse.rs
+++ b/openpgp/src/parse/parse.rs
@@ -1122,11 +1122,19 @@ impl CompressedData {
php.recursion_depth);
}
+ #[allow(unreachable_patterns)]
match algo {
+ CompressionAlgorithm::Uncompressed => (),
+ #[cfg(feature = "compression-deflate")]
+ CompressionAlgorithm::Zip
+ | CompressionAlgorithm::Zlib => (),
+ #[cfg(feature = "compression-bzip2")]
+ CompressionAlgorithm::BZip2 => (),
CompressionAlgorithm::Unknown(_)
| CompressionAlgorithm::Private(_) =>
return php.fail("unknown compression algorithm"),
- _ => (),
+ _ =>
+ return php.fail("unsupported compression algorithm"),
}
let recursion_depth = php.recursion_depth as usize;
@@ -1143,14 +1151,18 @@ impl CompressedData {
for a compression filter: this is an \
\"uncompressed compression packet\".");
}
+ let _ = recursion_depth;
reader
},
+ #[cfg(feature = "compression-deflate")]
CompressionAlgorithm::Zip =>
Box::new(BufferedReaderDeflate::with_cookie(
reader, Cookie::new(recursion_depth))),
+ #[cfg(feature = "compression-deflate")]
CompressionAlgorithm::Zlib =>
Box::new(BufferedReaderZlib::with_cookie(
reader, Cookie::new(recursion_depth))),
+ #[cfg(feature = "compression-bzip2")]
CompressionAlgorithm::BZip2 =>
Box::new(BufferedReaderBzip::with_cookie(
reader, Cookie::new(recursion_depth))),
@@ -1162,11 +1174,19 @@ impl CompressedData {
}
}
+#[cfg(any(feature = "compression-deflate", feature = "compression-bzip2"))]
#[test]
fn compressed_data_parser_test () {
let expected = bytes!("a-cypherpunks-manifesto.txt");
for i in 1..4 {
+ match CompressionAlgorithm::from(i) {
+ #[cfg(feature = "compression-deflate")]
+ CompressionAlgorithm::Zip | CompressionAlgorithm::Zlib => (),
+ #[cfg(feature = "compression-bzip2")]
+ CompressionAlgorithm::BZip2 => (),
+ _ => continue,
+ }
let path = path_to(&format!("compressed-data-algo-{}.gpg", i)[..]);
let mut pp = PacketParser::from_file(path).unwrap().unwrap();
@@ -2591,6 +2611,7 @@ impl<'a> BufferedReader<Cookie> for PacketParser<'a> {
// Check that we can use the read interface to stream the contents of
// a packet.
+#[cfg(feature = "compression-deflate")]
#[test]
fn packet_parser_reader_interface() {
// We need the Read trait.
diff --git a/openpgp/src/parse/subpacket.rs b/openpgp/src/parse/subpacket.rs
index 3d8b612a..0c58d76c 100644
--- a/openpgp/src/parse/subpacket.rs
+++ b/openpgp/src/parse/subpacket.rs
@@ -1480,6 +1480,7 @@ impl Signature {
}
}
+#[cfg(feature = "compression-deflate")]
#[test]
fn subpacket_test_1 () {
use PacketPile;
diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs
index 298536a2..01d51479 100644
--- a/openpgp/src/serialize/mod.rs
+++ b/openpgp/src/serialize/mod.rs
@@ -1034,6 +1034,7 @@ mod serialize_test {
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn serialize_test_2() {
// Given a packet in serialized form:
diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs
index 1434b677..012ceca8 100644
--- a/openpgp/src/serialize/stream.rs
+++ b/openpgp/src/serialize/stream.rs
@@ -542,10 +542,13 @@ impl<'a> Compressor<'a> {
let inner: writer::Stack<'a, Cookie> = match algo {
CompressionAlgorithm::Uncompressed =>
writer::Identity::new(inner, Cookie::new(level)),
+ #[cfg(feature = "compression-deflate")]
CompressionAlgorithm::Zip =>
writer::ZIP::new(inner, Cookie::new(level)),
+ #[cfg(feature = "compression-deflate")]
CompressionAlgorithm::Zlib =>
writer::ZLIB::new(inner, Cookie::new(level)),
+ #[cfg(feature = "compression-bzip2")]
CompressionAlgorithm::BZip2 =>
writer::BZ::new(inner, Cookie::new(level)),
_ => unimplemented!(),
@@ -1045,6 +1048,7 @@ mod test {
}
}
+ #[cfg(feature = "compression-deflate")]
#[test]
fn stream_big() {
let mut zeros = Vec::<u8>::new();
diff --git a/openpgp/src/serialize/writer.rs b/openpgp/src/serialize/writer/mod.rs
index 628187d1..39d21bcd 100644
--- a/openpgp/src/serialize/writer.rs
+++ b/openpgp/src/serialize/writer/mod.rs
@@ -1,9 +1,14 @@
//! Stackable writers.
-use bzip2::Compression as BzCompression;
-use bzip2::write::BzEncoder;
-use flate2::Compression as FlateCompression;
-use flate2::write::{DeflateEncoder, ZlibEncoder};
+#[cfg(feature = "compression-bzip2")]
+mod writer_bzip2;
+#[cfg(feature = "compression-bzip2")]
+pub use self::writer_bzip2::BZ;
+#[cfg(feature = "compression-deflate")]
+mod writer_deflate;
+#[cfg(feature = "compression-deflate")]
+pub use self::writer_deflate::{ZIP, ZLIB};
+
use std::fmt;
use std::io;
@@ -280,188 +285,6 @@ impl<'a, W: io::Write, C> Stackable<'a, C> for Generic<W, C> {
}
}
-/// ZIPing writer.
-pub struct ZIP<'a, C> {
- inner: Generic<DeflateEncoder<Stack<'a, C>>, C>,
-}
-
-impl<'a, C> ZIP<'a, C> {
- pub fn new(inner: Stack<'a, C>, cookie: C) -> Box<Self> {
- Box::new(ZIP {
- inner: Generic::new_unboxed(
- DeflateEncoder::new(inner, FlateCompression::default()),
- cookie),
- })
- }
-}
-
-impl<'a, C:> fmt::Debug for ZIP<'a, C> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("writer::ZIP")
- .field("inner", &self.inner)
- .finish()
- }
-}
-
-impl<'a, C> io::Write for ZIP<'a, C> {
- fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
- self.inner.write(bytes)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.inner.flush()
- }
-}
-
-impl<'a, C> Stackable<'a, C> for ZIP<'a, C> {
- fn into_inner(self: Box<Self>) -> Result<Option<Stack<'a, C>>> {
- let inner = self.inner.inner.finish()?;
- Ok(Some(inner))
- }
- fn pop(&mut self) -> Result<Option<Stack<'a, C>>> {
- unimplemented!()
- }
- fn mount(&mut self, _new: Stack<'a, C>) {
- unimplemented!()
- }
- fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> {
- self.inner.inner_mut()
- }
- fn inner_ref(&self) -> Option<&Stackable<'a, C>> {
- self.inner.inner_ref()
- }
- fn cookie_set(&mut self, cookie: C) -> C {
- self.inner.cookie_set(cookie)
- }
- fn cookie_ref(&self) -> &C {
- self.inner.cookie_ref()
- }
- fn cookie_mut(&mut self) -> &mut C {
- self.inner.cookie_mut()
- }
-}
-
-/// ZLIBing writer.
-pub struct ZLIB<'a, C> {
- inner: Generic<ZlibEncoder<Stack<'a, C>>, C>,
-}
-
-impl<'a, C> ZLIB<'a, C> {
- pub fn new(inner: Stack<'a, C>, cookie: C) -> Box<Self> {
- Box::new(ZLIB {
- inner: Generic::new_unboxed(
- ZlibEncoder::new(inner, FlateCompression::default()),
- cookie),
- })
- }
-}
-
-impl<'a, C:> fmt::Debug for ZLIB<'a, C> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("writer::ZLIB")
- .field("inner", &self.inner)
- .finish()
- }
-}
-
-impl<'a, C> io::Write for ZLIB<'a, C> {
- fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
- self.inner.write(bytes)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.inner.flush()
- }
-}
-
-impl<'a, C> Stackable<'a, C> for ZLIB<'a, C> {
- fn into_inner(sel