diff --git a/src/enc.rs b/src/enc.rs index 864094d..6459542 100644 --- a/src/enc.rs +++ b/src/enc.rs @@ -117,12 +117,15 @@ where F: AsyncRead + Unpin + ?Sized, Ok((written, read)) } -async fn de_singleton_inner(mut from: &[u8], how: &RecvOpt) -> Result +async fn de_singleton_inner(buf: F, mut from: &[u8], how: &RecvOpt) -> Result +where B: AsRef<[u8]> + AsyncWrite + Unpin, +F: FnOnce(&[u8]) -> B { // Decompressor // The output is written to this (through writer) let mut is_spec = false; //TODO: Determine this before allocating `buf`. - let mut buf = Vec::with_capacity(from.len()); // The `spec` output buffer. Used if there are transformations that need to be done to the data before deserialisation + let mut buf = buf(from); + //let mut buf = Vec::with_capacity(from.len()); // The `spec` output buffer. Used if there are transformations that need to be done to the data before deserialisation from = { let mut b; let writer: &mut (dyn AsyncWrite + Unpin) = @@ -147,11 +150,11 @@ async fn de_singleton_inner(mut from: &[u8], how: &RecvOpt) self::cha_copy::<_, _, DEFAULT_BUFSIZE, true>(&mut &from[..], writer, k, iv).await?; }, } - &buf[..] + &buf.as_ref()[..] } else if is_spec { // There is decompression to be done through `writer`. Return its output buffer writer.write_all(from).await?; - &buf[..] + &buf.as_ref()[..] } else { // There is neither decompression nor decryption to be done, return the input reference itself from @@ -207,7 +210,7 @@ where F: FnOnce(&Vec) -> V #[inline(always)] pub fn de_singleton<'a, T: DeserializeOwned + 'a, B: ?Sized + AsRef<[u8]> + 'a>(from: &'a B, how: &'a RecvOpt) -> impl Future> + 'a { use futures::prelude::*; - de_singleton_inner(from.as_ref(), how) + de_singleton_inner(|from| Vec::with_capacity(from.as_ref().len()), from.as_ref(), how) .map_err(|k| RecvError(Box::new((k, how.clone())))) } @@ -277,6 +280,30 @@ pub enum TransformErrorKind #[derive(Debug)] pub struct RecvError(Box<(TransformErrorKind, RecvOpt)>); +impl error::Error for RecvError +{ + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(match &self.0.0 + { + TransformErrorKind::IO(io) => io, + _ => return None, + }) + } +} +impl fmt::Display for RecvError +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, "error when deserialising object with params {:?}: ", self.0.1)?; + match self.0.0 { + TransformErrorKind::Format => write!(f, "failed to deserialise object to data"), + TransformErrorKind::Compress => write!(f, "failed to decompress data"), + TransformErrorKind::Encrypt => write!(f, "failed to decrypt data"), + TransformErrorKind::IO(_) => write!(f, "i/o failure"), + } + } +} + /// An error when sending / serialising an object. #[derive(Debug)]