summaryrefslogtreecommitdiffstats
path: root/openpgp/src/serialize/writer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/serialize/writer/mod.rs')
-rw-r--r--openpgp/src/serialize/writer/mod.rs140
1 files changed, 94 insertions, 46 deletions
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<Option<Stack<'a, C>>> {
+ 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<usize> {
+ self.0.write(buf)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.0.flush()
+ }
+}
+
+impl<'a, C> From<Stack<'a, C>> 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<Self>) -> Result<Option<Stack<'a, C>>>;
+ fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>>;
/// Pops the stackable from the stack, detaching it.
///
/// Returns the detached stack.
- fn pop(&mut self) -> Result<Option<Stack<'a, C>>>;
+ fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>>;
/// 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<Stackable>` look like a Stackable.
-impl <'a, C> Stackable<'a, C> for Stack<'a, C> {
- fn into_inner(self: Box<Self>) -> Result<Option<Stack<'a, C>>> {
+impl <'a, C> Stackable<'a, C> for BoxStack<'a, C> {
+ fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
(*self).into_inner()
}
/// Recovers the inner stackable.
- fn pop(&mut self) -> Result<Option<Stack<'a, C>>> {
+ fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
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<C, F>(head: &Stackable<C>, mut fun: F)
+pub(crate) fn map<C, F>(head: &Stackable<C>, mut fun: F)
where F: FnMut(&Stackable<C>) -> bool {
let mut ow = Some(head);
while let Some(w) = ow {
@@ -124,7 +168,7 @@ pub fn map<C, F>(head: &Stackable<C>, mut fun: F)
/// Maps a function over the stack of mutable writers.
#[allow(dead_code)]
-pub fn map_mut<C, F>(head: &mut Stackable<C>, mut fun: F)
+pub(crate) fn map_mut<C, F>(head: &mut Stackable<C>, mut fun: F)
where F: FnMut(&mut Stackable<C>) -> bool {
let mut ow = Some(head);
while let Some(w) = ow {
@@ -137,7 +181,7 @@ pub fn map_mut<C, F>(head: &mut Stackable<C>, mut fun: F)
/// Dumps the writer stack.
#[allow(dead_code)]
-pub fn dump<C>(head: &Stackable<C>) {
+pub(crate) fn dump<C>(head: &Stackable<C>) {
let mut depth = 0;
map(head, |w| {
eprintln!("{}: {:?}", depth, w);
@@ -146,15 +190,17 @@ pub fn dump<C>(head: &Stackable<C>) {
});
}
+/// The identity writer just relays anything written.
pub struct Identity<'a, C> {
- inner: Option<Stack<'a, C>>,
+ inner: Option<BoxStack<'a, C>>,
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<Self>) -> Result<Option<Stack<'a, C>>> {
+ fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
Ok(self.inner)
}
/// Recovers the inner stackable.
- fn pop(&mut self) -> Result<Option<Stack<'a, C>>> {
+ fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
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<W: io::Write, C> {
}
impl<'a, W: 'a + io::Write, C: 'a> Generic<W, C> {
+ /// 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<W: io::Write, C> io::Write for Generic<W, C> {
impl<'a, W: io::Write, C> Stackable<'a, C> for Generic<W, C> {
/// Recovers the inner stackable.
- fn into_inner(self: Box<Self>) -> Result<Option<Stack<'a, C>>> {
+ fn into_inner(self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
Ok(None)
}
/// Recovers the inner stackable.
- fn pop(&mut self) -> Result<Option<Stack<'a, C>>> {
+ fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
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<W, C> {
/// Encrypting writer.
-pub struct Encryptor<'a, C> {
- inner: Generic<symmetric::Encryptor<Stack<'a, C>>, C>,
+pub struct Encryptor<'a, C: 'a> {
+ inner: Generic<symmetric::Encryptor<BoxStack<'a, C>>, 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<Box<Self>>
+ -> Result<Stack<'a, C>>
{
- 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<usize> {
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<Self>) -> Result<Option<Stack<'a, C>>> {
+impl<'a, C: 'a> Stackable<'a, C> for Encryptor<'a, C> {
+ fn into_inner(mut self: Box<Self>) -> Result<Option<BoxStack<'a, C>>> {
let inner = self.inner.inner.finish()?;
Ok(Some(inner))
}
- fn pop(&mut self) -> Result<Option<Stack<'a, C>>> {
+ fn pop(&mut self) -> Result<Option<BoxStack<'a, C>>> {
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