From 222016e57c31135315d643c36c9328271c3bf19c Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Wed, 4 Jul 2018 12:57:22 +0200 Subject: openpgp: Hide the `writer::Stackable` trait. - Do not expose the `writer::Stackable` trait in the API. Instead, use a tuple struct to wrap boxed objects of this kind. - Add and use `writer::Stack::finalize()` and `writer::Stack::finalize_all()` to pop one or all writers from the stack. --- openpgp/examples/sign-detached.rs | 5 +- openpgp/examples/sign.rs | 9 +- openpgp/src/serialize/mod.rs | 2 +- openpgp/src/serialize/partial_body.rs | 14 +-- openpgp/src/serialize/stream.rs | 122 +++++++++++---------- openpgp/src/serialize/writer/mod.rs | 140 +++++++++++++++++-------- openpgp/src/serialize/writer/writer_bzip2.rs | 29 ++--- openpgp/src/serialize/writer/writer_deflate.rs | 54 +++++----- 8 files changed, 214 insertions(+), 161 deletions(-) (limited to 'openpgp') diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs index a4052907..3bbb9abd 100644 --- a/openpgp/examples/sign-detached.rs +++ b/openpgp/examples/sign-detached.rs @@ -40,7 +40,6 @@ fn main() { .expect("Failed to sign data"); // Teardown the stack to ensure all the data is written. - let _ = signer.into_inner() - .expect("Failed to write data") - .unwrap(); + signer.finalize_all() + .expect("Failed to write data"); } diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs index f1b8282d..2e212c78 100644 --- a/openpgp/examples/sign.rs +++ b/openpgp/examples/sign.rs @@ -45,11 +45,6 @@ fn main() { .expect("Failed to sign data"); // Teardown the stack to ensure all the data is written. - let signer = literal.into_inner() - .expect("Failed to write data") - .unwrap(); - - let _ = signer.into_inner() - .expect("Failed to write data") - .unwrap(); + literal.finalize_all() + .expect("Failed to write data"); } diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs index b336f579..ac97f150 100644 --- a/openpgp/src/serialize/mod.rs +++ b/openpgp/src/serialize/mod.rs @@ -16,7 +16,7 @@ use super::*; mod partial_body; use self::partial_body::PartialBodyFilter; -mod writer; +pub mod writer; pub mod stream; use s2k::S2K; use subpacket::{ diff --git a/openpgp/src/serialize/partial_body.rs b/openpgp/src/serialize/partial_body.rs index a1df796a..35c311ee 100644 --- a/openpgp/src/serialize/partial_body.rs +++ b/openpgp/src/serialize/partial_body.rs @@ -39,7 +39,7 @@ pub struct PartialBodyFilter<'a, C: 'a> { // Because this writer implements `Drop`, we cannot move the inner // writer out of this writer. We therefore wrap it with `Option` // so that we can `take()` it. - inner: Option>, + inner: Option>, // The cookie. cookie: C, @@ -66,13 +66,13 @@ impl<'a, C: 'a> PartialBodyFilter<'a, C> { pub fn new(inner: writer::Stack<'a, C>, cookie: C) -> writer::Stack<'a, C> { let buffer_threshold = PARTIAL_BODY_FILTER_BUFFER_THRESHOLD; let max_chunk_size = PARTIAL_BODY_FILTER_MAX_CHUNK_SIZE; - Box::new(PartialBodyFilter { - inner: Some(inner), + writer::Stack::from(Box::new(PartialBodyFilter { + inner: Some(inner.into()), cookie: cookie, buffer: Vec::with_capacity(buffer_threshold as usize), buffer_threshold: buffer_threshold, max_chunk_size: max_chunk_size, - }) + })) } // Writes out any full chunks between `self.buffer` and `other`. @@ -201,15 +201,15 @@ impl<'a, C: 'a> fmt::Debug for PartialBodyFilter<'a, C> { } impl<'a, C: 'a> writer::Stackable<'a, C> for PartialBodyFilter<'a, C> { - fn into_inner(mut self: Box) -> Result>> { + fn into_inner(mut self: Box) -> Result>> { self.write_out(&b""[..], true)?; Ok(self.inner.take()) } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { self.write_out(&b""[..], true)?; Ok(self.inner.take()) } - fn mount(&mut self, new: writer::Stack<'a, C>) { + fn mount(&mut self, new: writer::BoxStack<'a, C>) { self.inner = Some(new); } fn inner_mut(&mut self) -> Option<&mut writer::Stackable<'a, C>> { diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 67b828f2..ec605c0a 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -74,6 +74,7 @@ pub fn wrap<'a, W: 'a + io::Write>(w: W) -> writer::Stack<'a, Cookie> { /// # Example /// /// ``` +/// use std::io::Write; /// use openpgp::packet::Tag; /// use openpgp::serialize::stream::{wrap, ArbitraryWriter}; /// # use openpgp::Result; @@ -91,18 +92,18 @@ pub fn wrap<'a, W: 'a + io::Write>(w: W) -> writer::Stack<'a, Cookie> { /// # Ok(()) /// # } pub struct ArbitraryWriter<'a> { - inner: writer::Stack<'a, Cookie>, + inner: writer::BoxStack<'a, Cookie>, } impl<'a> ArbitraryWriter<'a> { /// Creates a new writer with the given tag. pub fn new(mut inner: writer::Stack<'a, Cookie>, tag: Tag) -> Result> { - let level = inner.cookie_ref().level + 1; + let level = inner.as_ref().cookie_ref().level + 1; CTB::new(tag).serialize(&mut inner)?; - Ok(Box::new(ArbitraryWriter { - inner: PartialBodyFilter::new(inner, Cookie::new(level)) - })) + Ok(writer::Stack::from(Box::new(ArbitraryWriter { + inner: PartialBodyFilter::new(inner, Cookie::new(level)).into() + }))) } } @@ -124,14 +125,14 @@ impl<'a> Write for ArbitraryWriter<'a> { } impl<'a> writer::Stackable<'a, Cookie> for ArbitraryWriter<'a> { - fn into_inner(self: Box) -> Result>> { + fn into_inner(self: Box) -> Result>> { Box::new(self.inner).into_inner() } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } /// Sets the inner stackable. - fn mount(&mut self, _new: writer::Stack<'a, Cookie>) { + fn mount(&mut self, _new: writer::BoxStack<'a, Cookie>) { unimplemented!() } fn inner_ref(&self) -> Option<&writer::Stackable<'a, Cookie>> { @@ -166,7 +167,7 @@ pub struct Signer<'a> { // Furthermore, the LiteralWriter will pop us off the stack, and // take our inner reader. If that happens, we only update the // digests. - inner: Option>, + inner: Option>, keys: Vec<&'a Key>, detached: bool, hash: Box, @@ -179,6 +180,7 @@ impl<'a> Signer<'a> { /// # Example /// /// ``` + /// use std::io::Write; /// use openpgp::serialize::stream::{wrap, Signer, LiteralWriter}; /// # use openpgp::{Result, TPK}; /// # let tsk = TPK::from_bytes(include_bytes!( @@ -191,8 +193,7 @@ impl<'a> Signer<'a> { /// let signer = Signer::new(wrap(&mut o), &[&tsk])?; /// let mut ls = LiteralWriter::new(signer, 't', None, 0)?; /// ls.write_all(b"Make it so, number one!")?; - /// let signer = ls.into_inner()?.unwrap(); - /// let _ = signer.into_inner()?.unwrap(); + /// ls.finalize_all()?; /// } /// # Ok(()) /// # } @@ -207,6 +208,7 @@ impl<'a> Signer<'a> { /// # Example /// /// ``` + /// use std::io::Write; /// use openpgp::serialize::stream::{wrap, Signer, LiteralWriter}; /// # use openpgp::{Result, TPK}; /// # let tsk = TPK::from_bytes(include_bytes!( @@ -219,7 +221,7 @@ impl<'a> Signer<'a> { /// let mut signer = Signer::detached(wrap(&mut o), &[&tsk])?; /// signer.write_all(b"Make it so, number one!")?; /// // In reality, just io::copy() the file to be signed. - /// let _ = signer.into_inner()?.unwrap(); + /// signer.finalize_all()?; /// } /// # Ok(()) /// # } @@ -229,9 +231,10 @@ impl<'a> Signer<'a> { Self::make(inner, signers, true) } - fn make(mut inner: writer::Stack<'a, Cookie>, signers: &[&'a TPK], + fn make(inner: writer::Stack<'a, Cookie>, signers: &[&'a TPK], detached: bool) -> Result> { + let mut inner = writer::BoxStack::from(inner); // Just always use SHA512. let hash_algo = HashAlgorithm::SHA512; let mut signing_keys = Vec::new(); @@ -306,7 +309,7 @@ impl<'a> Signer<'a> { } let level = inner.cookie_ref().level + 1; - Ok(Box::new(Signer { + Ok(writer::Stack::from(Box::new(Signer { inner: Some(inner), keys: signing_keys, detached: detached, @@ -315,7 +318,7 @@ impl<'a> Signer<'a> { level: level, private: Private::Signer, }, - })) + }))) } fn emit_signatures(&mut self) -> Result<()> { @@ -400,10 +403,10 @@ impl<'a> Write for Signer<'a> { } impl<'a> writer::Stackable<'a, Cookie> for Signer<'a> { - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { Ok(self.inner.take()) } - fn mount(&mut self, new: writer::Stack<'a, Cookie>) { + fn mount(&mut self, new: writer::BoxStack<'a, Cookie>) { self.inner = Some(new); } fn inner_mut(&mut self) -> Option<&mut writer::Stackable<'a, Cookie>> { @@ -421,7 +424,7 @@ impl<'a> writer::Stackable<'a, Cookie> for Signer<'a> { } } fn into_inner(mut self: Box) - -> Result>> { + -> Result>> { self.emit_signatures()?; Ok(self.inner.take()) } @@ -445,6 +448,7 @@ impl<'a> writer::Stackable<'a, Cookie> for Signer<'a> { /// # Example /// /// ``` +/// use std::io::Write; /// use openpgp::serialize::stream::{wrap, LiteralWriter}; /// # use openpgp::Result; /// # f().unwrap(); @@ -459,15 +463,16 @@ impl<'a> writer::Stackable<'a, Cookie> for Signer<'a> { /// # } /// ``` pub struct LiteralWriter<'a> { - inner: writer::Stack<'a, Cookie>, - signature_writer: Option>, + inner: writer::BoxStack<'a, Cookie>, + signature_writer: Option>, } impl<'a> LiteralWriter<'a> { /// Creates a new literal writer. - pub fn new(mut inner: writer::Stack<'a, Cookie>, + pub fn new(inner: writer::Stack<'a, Cookie>, format: char, filename: Option<&[u8]>, date: u32) -> Result> { + let mut inner = writer::BoxStack::from(inner); let level = inner.cookie_ref().level + 1; let mut template = Literal::new(format).date(date); @@ -505,15 +510,15 @@ impl<'a> LiteralWriter<'a> { // Neither is any framing added by the PartialBodyFilter. let mut inner - = PartialBodyFilter::new(inner, Cookie::new(level)); + = PartialBodyFilter::new(writer::Stack::from(inner), Cookie::new(level)); // Nor the headers. template.serialize_headers(&mut inner, false)?; - Ok(Box::new(Self { - inner: inner, + Ok(writer::Stack::from(Box::new(Self { + inner: inner.into(), signature_writer: signature_writer, - })) + }))) } } @@ -544,7 +549,7 @@ impl<'a> Write for LiteralWriter<'a> { impl<'a> writer::Stackable<'a, Cookie> for LiteralWriter<'a> { fn into_inner(mut self: Box) - -> Result>> { + -> Result>> { let signer = self.signature_writer.take(); let stack = self.inner .into_inner()?.unwrap(); // Peel off the PartialBodyFilter. @@ -559,11 +564,11 @@ impl<'a> writer::Stackable<'a, Cookie> for LiteralWriter<'a> { } } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } /// Sets the inner stackable. - fn mount(&mut self, _new: writer::Stack<'a, Cookie>) { + fn mount(&mut self, _new: writer::BoxStack<'a, Cookie>) { unimplemented!() } fn inner_ref(&self) -> Option<&writer::Stackable<'a, Cookie>> { @@ -591,6 +596,7 @@ impl<'a> writer::Stackable<'a, Cookie> for LiteralWriter<'a> { /// # Example /// /// ``` +/// use std::io::Write; /// use openpgp::serialize::stream::{wrap, Compressor, LiteralWriter}; /// use openpgp::constants::CompressionAlgorithm; /// # use openpgp::Result; @@ -608,23 +614,25 @@ impl<'a> writer::Stackable<'a, Cookie> for LiteralWriter<'a> { /// # Ok(()) /// # } pub struct Compressor<'a> { - inner: writer::Stack<'a, Cookie>, + inner: writer::BoxStack<'a, Cookie>, } impl<'a> Compressor<'a> { /// Creates a new compressor using the given algorithm. - pub fn new(mut inner: writer::Stack<'a, Cookie>, algo: CompressionAlgorithm) + pub fn new(inner: writer::Stack<'a, Cookie>, algo: CompressionAlgorithm) -> Result> { + let mut inner = writer::BoxStack::from(inner); let level = inner.cookie_ref().level + 1; // Packet header. CTB::new(Tag::CompressedData).serialize(&mut inner)?; let mut inner: writer::Stack<'a, Cookie> - = PartialBodyFilter::new(inner, Cookie::new(level)); + = PartialBodyFilter::new(writer::Stack::from(inner), + Cookie::new(level)); // Compressed data header. - inner.write_u8(algo.into())?; + inner.as_mut().write_u8(algo.into())?; // Create an appropriate filter. let inner: writer::Stack<'a, Cookie> = match algo { @@ -642,7 +650,7 @@ impl<'a> Compressor<'a> { _ => unimplemented!(), }; - Ok(Box::new(Self{inner: inner})) + Ok(writer::Stack::from(Box::new(Self{inner: inner.into()}))) } } @@ -665,14 +673,14 @@ impl<'a> io::Write for Compressor<'a> { } impl<'a> writer::Stackable<'a, Cookie> for Compressor<'a> { - fn into_inner(self: Box) -> Result>> { + fn into_inner(self: Box) -> Result>> { Box::new(self.inner).into_inner()?.unwrap().into_inner() } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } /// Sets the inner stackable. - fn mount(&mut self, _new: writer::Stack<'a, Cookie>) { + fn mount(&mut self, _new: writer::BoxStack<'a, Cookie>) { unimplemented!() } fn inner_ref(&self) -> Option<&writer::Stackable<'a, Cookie>> { @@ -694,7 +702,7 @@ impl<'a> writer::Stackable<'a, Cookie> for Compressor<'a> { /// Encrypts a packet stream. pub struct Encryptor<'a> { - inner: Option>, + inner: Option>, hash: Box, cookie: Cookie, } @@ -731,6 +739,7 @@ impl<'a> Encryptor<'a> { /// # Example /// /// ``` + /// use std::io::Write; /// #[macro_use] extern crate openpgp; // For armored! /// use openpgp::serialize::stream::{ /// wrap, Encryptor, EncryptionMode, LiteralWriter, @@ -791,7 +800,7 @@ impl<'a> Encryptor<'a> { encryption_mode: EncryptionMode) -> Result> { let mut rng = Yarrow::default(); - let level = inner.cookie_ref().level + 1; + let level = inner.as_ref().cookie_ref().level + 1; let algo = SymmetricAlgorithm::AES256; // Generate a session key. @@ -870,13 +879,12 @@ impl<'a> Encryptor<'a> { // Write the SEIP packet. CTB::new(Tag::SEIP).serialize(&mut inner)?; - let mut inner: writer::Stack<'a, Cookie> - = PartialBodyFilter::new(inner, Cookie::new(level)); + let mut inner = PartialBodyFilter::new(inner, Cookie::new(level)); inner.write(&[1])?; // Version. // Assuming 'algo' is good, this cannot fail. let encryptor = writer::Encryptor::new( - inner, + inner.into(), Cookie::new(level), algo, &sk, @@ -884,11 +892,11 @@ impl<'a> Encryptor<'a> { // The hash for the MDC must include the initialization // vector, hence we build the object here. - let mut encryptor = Box::new(Self{ - inner: Some(encryptor), + let mut encryptor = writer::Stack::from(Box::new(Self{ + inner: Some(encryptor.into()), hash: HashAlgorithm::SHA1.context().unwrap(), cookie: Cookie::new(level), - }); + })); // Write the initialization vector, and the quick-check bytes. let mut iv = vec![0; algo.block_size().unwrap()]; @@ -900,7 +908,7 @@ impl<'a> Encryptor<'a> { } /// Emits the MDC packet and recovers the original writer. - fn emit_mdc(&mut self) -> Result> { + fn emit_mdc(&mut self) -> Result> { if let Some(mut w) = self.inner.take() { // Write the MDC, which must be the last packet inside the // encrypted packet stream. The hash includes the MDC's @@ -961,11 +969,11 @@ impl<'a> Write for Encryptor<'a> { } impl<'a> writer::Stackable<'a, Cookie> for Encryptor<'a> { - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } /// Sets the inner stackable. - fn mount(&mut self, _new: writer::Stack<'a, Cookie>) { + fn mount(&mut self, _new: writer::BoxStack<'a, Cookie>) { unimplemented!() } fn inner_ref(&self) -> Option<&writer::Stackable<'a, Cookie>> { @@ -982,7 +990,7 @@ impl<'a> writer::Stackable<'a, Cookie> for Encryptor<'a> { None } } - fn into_inner(mut self: Box) -> Result>> { + fn into_inner(mut self: Box) -> Result>> { Ok(Some(self.emit_mdc()?)) } fn cookie_set(&mut self, cookie: Cookie) -> Cookie { @@ -1059,11 +1067,11 @@ mod test { wrap(&mut o), CompressionAlgorithm::Uncompressed).unwrap(); let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "one").unwrap(); - let c = ls.into_inner().unwrap().unwrap(); // Pop the LiteralWriter. + let c = ls.finalize().unwrap().unwrap(); // Pop the LiteralWriter. let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "two").unwrap(); - let c = ls.into_inner().unwrap().unwrap(); // Pop the LiteralWriter. - let c = c.into_inner().unwrap().unwrap(); // Pop the Compressor. + let c = ls.finalize().unwrap().unwrap(); // Pop the LiteralWriter. + let c = c.finalize().unwrap().unwrap(); // Pop the Compressor. let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "three").unwrap(); } @@ -1111,16 +1119,16 @@ mod test { c0, CompressionAlgorithm::Uncompressed).unwrap(); let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "one").unwrap(); - let c = ls.into_inner().unwrap().unwrap(); + let c = ls.finalize().unwrap().unwrap(); let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "two").unwrap(); - let c = ls.into_inner().unwrap().unwrap(); - let c0 = c.into_inner().unwrap().unwrap(); + let c = ls.finalize().unwrap().unwrap(); + let c0 = c.finalize().unwrap().unwrap(); let c = Compressor::new( c0, CompressionAlgorithm::Uncompressed).unwrap(); let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "three").unwrap(); - let c = ls.into_inner().unwrap().unwrap(); + let c = ls.finalize().unwrap().unwrap(); let mut ls = LiteralWriter::new(c, 't', None, 0).unwrap(); write!(ls, "four").unwrap(); } @@ -1173,8 +1181,8 @@ mod test { .unwrap(); let mut ls = LiteralWriter::new(signer, 't', None, 0).unwrap(); ls.write_all(b"Tis, tis, tis. Tis is important.").unwrap(); - let signer = ls.into_inner().unwrap().unwrap(); - let _ = signer.into_inner().unwrap().unwrap(); + let signer = ls.finalize().unwrap().unwrap(); + let _ = signer.finalize().unwrap().unwrap(); } let mut ppr = PacketParser::from_bytes(&o).unwrap(); diff --git a/openpgp/src/serialize/writer/mod.rs b/openpgp/src/serialize/writer/mod.rs index 39d21bcd..9815fcc0 100644 --- a/openpgp/src/serialize/writer/mod.rs +++ b/openpgp/src/serialize/writer/mod.rs @@ -19,26 +19,70 @@ use { }; /// A stack of writers. -/// -/// We use trait objects as the unit of composition. This is a -/// compiler limitation, we may use impl trait in the future. -pub type Stack<'a, C> = Box<'a + Stackable<'a, C>>; +#[derive(Debug)] +pub struct Stack<'a, C>(BoxStack<'a, C>); + +impl<'a, C> Stack<'a, C> { + pub(crate) fn from(bs: BoxStack<'a, C>) -> Self { + Stack(bs) + } + + pub(crate) fn as_ref(&self) -> &BoxStack<'a, C> { + &self.0 + } + + pub(crate) fn as_mut(&mut self) -> &mut BoxStack<'a, C> { + &mut self.0 + } + + /// Finalizes this writer, returning the underlying writer. + pub fn finalize(self) -> Result>> { + Ok(self.0.into_inner()?.map(|bs| Self::from(bs))) + } + + /// Finalizes all writers, tearing down the whole stack. + pub fn finalize_all(self) -> Result<()> { + let mut stack = self; + while let Some(s) = stack.finalize()? { + stack = s; + } + Ok(()) + } +} + +impl<'a, C> io::Write for Stack<'a, C> { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } +} + +impl<'a, C> From> for BoxStack<'a, C> { + fn from(s: Stack<'a, C>) -> Self { + s.0 + } +} + +pub(crate) type BoxStack<'a, C> = Box<'a + Stackable<'a, C>>; /// Makes a writer stackable and provides convenience functions. -pub trait Stackable<'a, C> : io::Write + fmt::Debug { +pub(crate) trait Stackable<'a, C> : io::Write + fmt::Debug { /// Recovers the inner stackable. /// /// This can fail if the current `Stackable` has buffered data /// that hasn't been written to the underlying `Stackable`. - fn into_inner(self: Box) -> Result>>; + fn into_inner(self: Box) -> Result>>; /// Pops the stackable from the stack, detaching it. /// /// Returns the detached stack. - fn pop(&mut self) -> Result>>; + fn pop(&mut self) -> Result>>; /// Sets the inner stackable. - fn mount(&mut self, new: Stack<'a, C>); + fn mount(&mut self, new: BoxStack<'a, C>); /// Returns a mutable reference to the inner `Writer`, if /// any. @@ -80,16 +124,16 @@ pub trait Stackable<'a, C> : io::Write + fmt::Debug { } /// Make a `Box` look like a Stackable. -impl <'a, C> Stackable<'a, C> for Stack<'a, C> { - fn into_inner(self: Box) -> Result>> { +impl <'a, C> Stackable<'a, C> for BoxStack<'a, C> { + fn into_inner(self: Box) -> Result>> { (*self).into_inner() } /// Recovers the inner stackable. - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { self.as_mut().pop() } /// Sets the inner stackable. - fn mount(&mut self, new: Stack<'a, C>) { + fn mount(&mut self, new: BoxStack<'a, C>) { self.as_mut().mount(new); } fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> { @@ -111,7 +155,7 @@ impl <'a, C> Stackable<'a, C> for Stack<'a, C> { /// Maps a function over the stack of writers. #[allow(dead_code)] -pub fn map(head: &Stackable, mut fun: F) +pub(crate) fn map(head: &Stackable, mut fun: F) where F: FnMut(&Stackable) -> bool { let mut ow = Some(head); while let Some(w) = ow { @@ -124,7 +168,7 @@ pub fn map(head: &Stackable, mut fun: F) /// Maps a function over the stack of mutable writers. #[allow(dead_code)] -pub fn map_mut(head: &mut Stackable, mut fun: F) +pub(crate) fn map_mut(head: &mut Stackable, mut fun: F) where F: FnMut(&mut Stackable) -> bool { let mut ow = Some(head); while let Some(w) = ow { @@ -137,7 +181,7 @@ pub fn map_mut(head: &mut Stackable, mut fun: F) /// Dumps the writer stack. #[allow(dead_code)] -pub fn dump(head: &Stackable) { +pub(crate) fn dump(head: &Stackable) { let mut depth = 0; map(head, |w| { eprintln!("{}: {:?}", depth, w); @@ -146,15 +190,17 @@ pub fn dump(head: &Stackable) { }); } +/// The identity writer just relays anything written. pub struct Identity<'a, C> { - inner: Option>, + inner: Option>, cookie: C, } impl<'a, C: 'a> Identity<'a, C> { + /// Makes an identity writer. pub fn new(inner: Stack<'a, C>, cookie: C) -> Stack<'a, C> { - Box::new(Self{inner: Some(inner), cookie: cookie}) + Stack::from(Box::new(Self{inner: Some(inner.into()), cookie: cookie})) } } @@ -184,15 +230,15 @@ impl<'a, C> io::Write for Identity<'a, C> { impl<'a, C> Stackable<'a, C> for Identity<'a, C> { /// Recovers the inner stackable. - fn into_inner(self: Box) -> Result>> { + fn into_inner(self: Box) -> Result>> { Ok(self.inner) } /// Recovers the inner stackable. - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { Ok(self.inner.take()) } /// Sets the inner stackable. - fn mount(&mut self, new: Stack<'a, C>) { + fn mount(&mut self, new: BoxStack<'a, C>) { self.inner = Some(new); } fn inner_ref(&self) -> Option<&Stackable<'a, C>> { @@ -227,8 +273,9 @@ pub struct Generic { } impl<'a, W: 'a + io::Write, C: 'a> Generic { + /// Wraps an `io::Write`r. pub fn new(inner: W, cookie: C) -> Stack<'a, C> { - Box::new(Self::new_unboxed(inner, cookie)) + Stack::from(Box::new(Self::new_unboxed(inner.into(), cookie))) } fn new_unboxed(inner: W, cookie: C) -> Self { @@ -258,15 +305,15 @@ impl io::Write for Generic { impl<'a, W: io::Write, C> Stackable<'a, C> for Generic { /// Recovers the inner stackable. - fn into_inner(self: Box) -> Result>> { + fn into_inner(self: Box) -> Result>> { Ok(None) } /// Recovers the inner stackable. - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { Ok(None) } /// Sets the inner stackable. - fn mount(&mut self, _new: Stack<'a, C>) { + fn mount(&mut self, _new: BoxStack<'a, C>) { } fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> { None @@ -287,24 +334,25 @@ impl<'a, W: io::Write, C> Stackable<'a, C> for Generic { /// Encrypting writer. -pub struct Encryptor<'a, C> { - inner: Generic>, C>, +pub struct Encryptor<'a, C: 'a> { + inner: Generic>, C>, } -impl<'a, C> Encryptor<'a, C> { +impl<'a, C: 'a> Encryptor<'a, C> { + /// Makes an encrypting writer. pub fn new(inner: Stack<'a, C>, cookie: C, algo: SymmetricAlgorithm, key: &[u8]) - -> Result> + -> Result> { - Ok(Box::new(Encryptor { + Ok(Stack::from(Box::new(Encryptor { inner: Generic::new_unboxed( - symmetric::Encryptor::new(algo, key, inner)?, + symmetric::Encryptor::new(algo, key, inner.into())?, cookie), - })) + }))) } } -impl<'a, C:> fmt::Debug for Encryptor<'a, C> { +impl<'a, C: 'a> fmt::Debug for Encryptor<'a, C> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("writer::Encryptor") .field("inner", &self.inner) @@ -312,7 +360,7 @@ impl<'a, C:> fmt::Debug for Encryptor<'a, C> { } } -impl<'a, C> io::Write for Encryptor<'a, C> { +impl<'a, C: 'a> io::Write for Encryptor<'a, C> { fn write(&mut self, bytes: &[u8]) -> io::Result { self.inner.write(bytes) } @@ -322,15 +370,15 @@ impl<'a, C> io::Write for Encryptor<'a, C> { } } -impl<'a, C> Stackable<'a, C> for Encryptor<'a, C> { - fn into_inner(mut self: Box) -> Result>> { +impl<'a, C: 'a> Stackable<'a, C> for Encryptor<'a, C> { + fn into_inner(mut self: Box) -> Result>> { let inner = self.inner.inner.finish()?; Ok(Some(inner)) } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } - fn mount(&mut self, _new: Stack<'a, C>) { + fn mount(&mut self, _new: BoxStack<'a, C>) { unimplemented!() } fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> { @@ -365,15 +413,15 @@ mod test { let mut inner = Vec::new(); { let mut w = Generic::new(&mut inner, Cookie { state: "happy" }); - assert_eq!(w.cookie_ref().state, "happy"); - dump(&w); + assert_eq!(w.as_ref().cookie_ref().state, "happy"); + dump(w.as_ref()); - w.cookie_mut().state = "sad"; - assert_eq!(w.cookie_ref().state, "sad"); + w.as_mut().cookie_mut().state = "sad"; + assert_eq!(w.as_ref().cookie_ref().state, "sad"); w.write_all(b"be happy").unwrap(); let mut count = 0; - map_mut(&mut w, |g| { + map_mut(w.as_mut(), |g| { let new = Cookie { state: "happy" }; let old = g.cookie_set(new); assert_eq!(old.state, "sad"); @@ -381,7 +429,7 @@ mod test { true }); assert_eq!(count, 1); - assert_eq!(w.cookie_ref().state, "happy"); + assert_eq!(w.as_ref().cookie_ref().state, "happy"); } assert_eq!(&inner, b"be happy"); } @@ -391,13 +439,13 @@ mod test { let mut inner = Vec::new(); { let w = Generic::new(&mut inner, Cookie { state: "happy" }); - dump(&w); + dump(w.as_ref()); let w = Identity::new(w, Cookie { state: "happy" }); - dump(&w); + dump(w.as_ref()); let mut count = 0; - map(&w, |g| { + map(w.as_ref(), |g| { assert_eq!(g.cookie_ref().state, "happy"); count += 1; true diff --git a/openpgp/src/serialize/writer/writer_bzip2.rs b/openpgp/src/serialize/writer/writer_bzip2.rs index 4411e574..d0189821 100644 --- a/openpgp/src/serialize/writer/writer_bzip2.rs +++ b/openpgp/src/serialize/writer/writer_bzip2.rs @@ -4,24 +4,25 @@ use std::fmt; use std::io; use Result; -use super::{Generic, Stack, Stackable}; +use super::{Generic, Stack, BoxStack, Stackable}; /// BZing writer. -pub struct BZ<'a, C> { - inner: Generic>, C>, +pub struct BZ<'a, C: 'a> { + inner: Generic>, C>, } -impl<'a, C> BZ<'a, C> { - pub fn new(inner: Stack<'a, C>, cookie: C) -> Box { - Box::new(BZ { +impl<'a, C: 'a> BZ<'a, C> { + /// Makes a BZ compressing writer. + pub fn new(inner: Stack<'a, C>, cookie: C) -> Stack<'a, C> { + Stack::from(Box::new(BZ { inner: Generic::new_unboxed( - BzEncoder::new(inner, BzCompression::Default), + BzEncoder::new(inner.into(), BzCompression::Default), cookie), - }) + })) } } -impl<'a, C:> fmt::Debug for BZ<'a, C> { +impl<'a, C: 'a> fmt::Debug for BZ<'a, C> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("writer::BZ") .field("inner", &self.inner) @@ -29,7 +30,7 @@ impl<'a, C:> fmt::Debug for BZ<'a, C> { } } -impl<'a, C> io::Write for BZ<'a, C> { +impl<'a, C: 'a> io::Write for BZ<'a, C> { fn write(&mut self, bytes: &[u8]) -> io::Result { self.inner.write(bytes) } @@ -39,15 +40,15 @@ impl<'a, C> io::Write for BZ<'a, C> { } } -impl<'a, C> Stackable<'a, C> for BZ<'a, C> { - fn into_inner(self: Box) -> Result>> { +impl<'a, C: 'a> Stackable<'a, C> for BZ<'a, C> { + fn into_inner(self: Box) -> Result>> { let inner = self.inner.inner.finish()?; Ok(Some(inner)) } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } - fn mount(&mut self, _new: Stack<'a, C>) { + fn mount(&mut self, _new: BoxStack<'a, C>) { unimplemented!() } fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> { diff --git a/openpgp/src/serialize/writer/writer_deflate.rs b/openpgp/src/serialize/writer/writer_deflate.rs index 54900dff..f5cdcb7d 100644 --- a/openpgp/src/serialize/writer/writer_deflate.rs +++ b/openpgp/src/serialize/writer/writer_deflate.rs @@ -4,24 +4,25 @@ use std::fmt; use std::io; use Result; -use super::{Generic, Stack, Stackable}; +use super::{Generic, Stack, BoxStack, Stackable}; /// ZIPing writer. -pub struct ZIP<'a, C> { - inner: Generic>, C>, +pub struct ZIP<'a, C: 'a> { + inner: Generic>, C>, } -impl<'a, C> ZIP<'a, C> { - pub fn new(inner: Stack<'a, C>, cookie: C) -> Box { - Box::new(ZIP { +impl<'a, C: 'a> ZIP<'a, C> { + /// Makes a ZIP compressing writer. + pub fn new(inner: Stack<'a, C>, cookie: C) -> Stack<'a, C> { + Stack::from(Box::new(ZIP { inner: Generic::new_unboxed( - DeflateEncoder::new(inner, FlateCompression::default()), + DeflateEncoder::new(inner.into(), FlateCompression::default()), cookie), - }) + })) } } -impl<'a, C:> fmt::Debug for ZIP<'a, C> { +impl<'a, C: 'a> fmt::Debug for ZIP<'a, C> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("writer::ZIP") .field("inner", &self.inner) @@ -29,7 +30,7 @@ impl<'a, C:> fmt::Debug for ZIP<'a, C> { } } -impl<'a, C> io::Write for ZIP<'a, C> { +impl<'a, C: 'a> io::Write for ZIP<'a, C> { fn write(&mut self, bytes: &[u8]) -> io::Result { self.inner.write(bytes) } @@ -39,15 +40,15 @@ impl<'a, C> io::Write for ZIP<'a, C> { } } -impl<'a, C> Stackable<'a, C> for ZIP<'a, C> { - fn into_inner(self: Box) -> Result>> { +impl<'a, C: 'a> Stackable<'a, C> for ZIP<'a, C> { + fn into_inner(self: Box) -> Result>> { let inner = self.inner.inner.finish()?; Ok(Some(inner)) } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } - fn mount(&mut self, _new: Stack<'a, C>) { + fn mount(&mut self, _new: BoxStack<'a, C>) { unimplemented!() } fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> { @@ -68,17 +69,18 @@ impl<'a, C> Stackable<'a, C> for ZIP<'a, C> { } /// ZLIBing writer. -pub struct ZLIB<'a, C> { - inner: Generic>, C>, +pub struct ZLIB<'a, C: 'a> { + inner: Generic>, C>, } -impl<'a, C> ZLIB<'a, C> { - pub fn new(inner: Stack<'a, C>, cookie: C) -> Box { - Box::new(ZLIB { +impl<'a, C: 'a> ZLIB<'a, C> { + /// Makes a ZLIB compressing writer. + pub fn new(inner: Stack<'a, C>, cookie: C) -> Stack<'a, C> { + Stack::from(Box::new(ZLIB { inner: Generic::new_unboxed( - ZlibEncoder::new(inner, FlateCompression::default()), + ZlibEncoder::new(inner.into(), FlateCompression::default()), cookie), - }) + })) } } @@ -90,7 +92,7 @@ impl<'a, C:> fmt::Debug for ZLIB<'a, C> { } } -impl<'a, C> io::Write for ZLIB<'a, C> { +impl<'a, C: 'a> io::Write for ZLIB<'a, C> { fn write(&mut self, bytes: &[u8]) -> io::Result { self.inner.write(bytes) } @@ -100,15 +102,15 @@ impl<'a, C> io::Write for ZLIB<'a, C> { } } -impl<'a, C> Stackable<'a, C> for ZLIB<'a, C> { - fn into_inner(self: Box) -> Result>> { +impl<'a, C: 'a> Stackable<'a, C> for ZLIB<'a, C> { + fn into_inner(self: Box) -> Result>> { let inner = self.inner.inner.finish()?; Ok(Some(inner)) } - fn pop(&mut self) -> Result>> { + fn pop(&mut self) -> Result>> { unimplemented!() } - fn mount(&mut self, _new: Stack<'a, C>) { + fn mount(&mut self, _new: BoxStack<'a, C>) { unimplemented!() } fn inner_mut(&mut self) -> Option<&mut Stackable<'a, C>> { -- cgit v1.2.3