|
|
|
@ -75,18 +75,7 @@ pub struct SendOpt
|
|
|
|
|
}
|
|
|
|
|
ref_self!(SendOpt);
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Default)]
|
|
|
|
|
pub struct RecvOpt
|
|
|
|
|
{
|
|
|
|
|
pub comp: Option<CompressionKind>,
|
|
|
|
|
pub handle_encrypted: Option<EncryptionKind>,
|
|
|
|
|
pub format: SerialFormat,
|
|
|
|
|
/// Max size of the (decompressed) input buffer.
|
|
|
|
|
/// 0 for unlimited.
|
|
|
|
|
//TODO: Do we need this?
|
|
|
|
|
pub max_size: usize,
|
|
|
|
|
}
|
|
|
|
|
ref_self!(RecvOpt);
|
|
|
|
|
pub type RecvOpt = SendOpt;
|
|
|
|
|
|
|
|
|
|
/// Default buffer size for encryption transform stream copying.
|
|
|
|
|
pub const DEFAULT_BUFSIZE: usize = 4096;
|
|
|
|
@ -119,7 +108,7 @@ where F: AsyncRead + Unpin + ?Sized,
|
|
|
|
|
|
|
|
|
|
async fn de_singleton_inner<T: DeserializeOwned, B, F>(buf: F, mut from: &[u8], how: &RecvOpt) -> Result<T, TransformErrorKind>
|
|
|
|
|
where B: AsRef<[u8]> + AsyncWrite + Unpin,
|
|
|
|
|
F: FnOnce(&[u8]) -> B
|
|
|
|
|
F: FnOnce(&[u8]) -> B
|
|
|
|
|
{
|
|
|
|
|
// Decompressor
|
|
|
|
|
// The output is written to this (through writer)
|
|
|
|
@ -142,7 +131,8 @@ F: FnOnce(&[u8]) -> B
|
|
|
|
|
&mut buf
|
|
|
|
|
};
|
|
|
|
|
// Decrypt into `writer`.
|
|
|
|
|
if let Some(dec) = &how.handle_encrypted {
|
|
|
|
|
|
|
|
|
|
if let Some(dec) = &how.encrypt {
|
|
|
|
|
// There is decryption to be done, decrypt into `writer` (which will handle decompression if needed).
|
|
|
|
|
// Return its output buffer
|
|
|
|
|
match dec {
|
|
|
|
@ -150,10 +140,19 @@ F: FnOnce(&[u8]) -> B
|
|
|
|
|
self::cha_copy::<_, _, DEFAULT_BUFSIZE, true>(&mut &from[..], writer, k, iv).await?;
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
// Required for decompression to complete
|
|
|
|
|
writer.flush().await?;
|
|
|
|
|
writer.shutdown().await?;
|
|
|
|
|
|
|
|
|
|
&buf.as_ref()[..]
|
|
|
|
|
} else if is_spec {
|
|
|
|
|
// There is decompression to be done through `writer`. Return its output buffer
|
|
|
|
|
writer.write_all(from).await?;
|
|
|
|
|
|
|
|
|
|
// Required for decompression to complete
|
|
|
|
|
writer.flush().await?;
|
|
|
|
|
writer.shutdown().await?;
|
|
|
|
|
|
|
|
|
|
&buf.as_ref()[..]
|
|
|
|
|
} else {
|
|
|
|
|
// There is neither decompression nor decryption to be done, return the input reference itself
|
|
|
|
@ -195,11 +194,15 @@ where F: FnOnce(&Vec<u8>) -> V
|
|
|
|
|
};
|
|
|
|
|
let mut ser = to(&ser);
|
|
|
|
|
let w= if let Some(enc) = &how.encrypt {
|
|
|
|
|
match enc {
|
|
|
|
|
let n = match enc {
|
|
|
|
|
EncryptionKind::Chacha20((k, iv)) => {
|
|
|
|
|
self::cha_copy::<_, _, DEFAULT_BUFSIZE, false>(reader, &mut ser, k, iv).await?.0
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// Required for compression to complete
|
|
|
|
|
ser.flush().await?;
|
|
|
|
|
ser.shutdown().await?;
|
|
|
|
|
n
|
|
|
|
|
} else {
|
|
|
|
|
tokio::io::copy(reader, &mut ser).await? as usize
|
|
|
|
|
};
|
|
|
|
@ -358,3 +361,56 @@ impl From<serde_json::Error> for TransformErrorKind
|
|
|
|
|
Self::Format
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test
|
|
|
|
|
{
|
|
|
|
|
use super::*;
|
|
|
|
|
async fn ser_de_with(how: SendOpt) -> eyre::Result<()>
|
|
|
|
|
{
|
|
|
|
|
use ext::*;
|
|
|
|
|
|
|
|
|
|
let obj = String::from("Hello world");
|
|
|
|
|
|
|
|
|
|
let var = ser_singleton(&obj, &how).await?;
|
|
|
|
|
eprintln!("Ser: {}", var.hex());
|
|
|
|
|
let des: String = de_singleton(&var, &how).await?;
|
|
|
|
|
eprintln!("De: {:?}", des);
|
|
|
|
|
assert_eq!(obj, des);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn ser_de() -> eyre::Result<()>
|
|
|
|
|
{
|
|
|
|
|
ser_de_with(Default::default()).await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn ser_de_comp() -> eyre::Result<()>
|
|
|
|
|
{
|
|
|
|
|
ser_de_with(SendOpt {
|
|
|
|
|
comp: Some(CompressionKind::Brotli),
|
|
|
|
|
..Default::default()
|
|
|
|
|
}).await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn ser_de_enc() -> eyre::Result<()>
|
|
|
|
|
{
|
|
|
|
|
ser_de_with(SendOpt {
|
|
|
|
|
encrypt: Some(EncryptionKind::Chacha20(cha::keygen())),
|
|
|
|
|
..Default::default()
|
|
|
|
|
}).await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn ser_de_comp_enc() -> eyre::Result<()>
|
|
|
|
|
{
|
|
|
|
|
ser_de_with(SendOpt {
|
|
|
|
|
encrypt: Some(EncryptionKind::Chacha20(cha::keygen())),
|
|
|
|
|
comp: Some(CompressionKind::Brotli),
|
|
|
|
|
..Default::default()
|
|
|
|
|
}).await
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|