feat: add compress util
This commit is contained in:
20
Cargo.lock
generated
20
Cargo.lock
generated
@@ -430,6 +430,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.5.3"
|
||||
@@ -671,6 +680,16 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@@ -2162,6 +2181,7 @@ dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
"clap",
|
||||
"flate2",
|
||||
"hex",
|
||||
"openpgp-card",
|
||||
"openpgp-card-pcsc",
|
||||
|
||||
@@ -13,6 +13,7 @@ aes-gcm-stream = "0.2.0"
|
||||
base64 = "0.21.0"
|
||||
chrono = "0.4.23"
|
||||
clap = { version = "4.1.4", features = ["derive"] }
|
||||
flate2 = "1.0.27"
|
||||
hex = "0.4.3"
|
||||
openpgp-card = "0.3.7"
|
||||
openpgp-card-pcsc = "0.3.0"
|
||||
|
||||
125
src/compress.rs
Normal file
125
src/compress.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use std::io::Write;
|
||||
|
||||
use flate2::Compression;
|
||||
use flate2::write::{GzDecoder, GzEncoder};
|
||||
use rust_util::XResult;
|
||||
use x509_parser::nom::AsBytes;
|
||||
|
||||
pub struct GzStreamEncoder {
|
||||
gz_encoder: GzEncoder<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl GzStreamEncoder {
|
||||
pub fn new_default() -> Self {
|
||||
GzStreamEncoder::new(Compression::default())
|
||||
}
|
||||
|
||||
pub fn new(compression: Compression) -> Self {
|
||||
let buffer = Vec::with_capacity(1024 * 8);
|
||||
let gz_encoder = GzEncoder::new(buffer, compression);
|
||||
Self { gz_encoder }
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buff: &[u8]) -> XResult<Vec<u8>> {
|
||||
self.gz_encoder.write_all(buff)?;
|
||||
let inner = self.gz_encoder.get_mut();
|
||||
let result = inner.clone();
|
||||
inner.clear();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn finalize(mut self) -> Result<Vec<u8>, String> {
|
||||
match self.gz_encoder.finish() {
|
||||
Ok(last_buffer) => Ok(last_buffer),
|
||||
Err(e) => Err(format!("Decode stream failed: {}", e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GzStreamDecoder {
|
||||
gz_decoder: GzDecoder<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl GzStreamDecoder {
|
||||
pub fn new() -> Self {
|
||||
let buffer = Vec::with_capacity(1024 * 8);
|
||||
let gz_decoder = GzDecoder::new(buffer);
|
||||
Self { gz_decoder }
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buff: &[u8]) -> XResult<Vec<u8>> {
|
||||
self.gz_decoder.write_all(buff)?;
|
||||
let inner = self.gz_decoder.get_mut();
|
||||
let result = inner.clone();
|
||||
inner.clear();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn finalize(mut self) -> Result<Vec<u8>, String> {
|
||||
match self.gz_decoder.finish() {
|
||||
Ok(last_buffer) => Ok(last_buffer),
|
||||
Err(e) => Err(format!("Decode stream failed: {}", e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gzip_compress() {
|
||||
for (compressed, decompressed) in vec![
|
||||
("1f8b0800000000000000f348cdc9c95708cf2fca49010056b1174a0b000000", "Hello World"),
|
||||
(
|
||||
"1f8b0800000000000000f348cdc9c95708cf2fca49f12081090044f4575937000000",
|
||||
"Hello WorldHello WorldHello WorldHello WorldHello World"
|
||||
),
|
||||
] {
|
||||
let compressed = hex::decode(compressed).unwrap();
|
||||
let mut decoder = GzStreamDecoder::new();
|
||||
let mut decompressed_bytes = decoder.update(&compressed).unwrap();
|
||||
let last_buffer = decoder.finalize().unwrap();
|
||||
decompressed_bytes.extend_from_slice(&last_buffer);
|
||||
assert_eq!(decompressed, String::from_utf8(decompressed_bytes).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gzip_compress_multi_blocks() {
|
||||
let compressed = hex::decode("1f8b0800000000000000f348cdc9c95708cf2fca49f12081090044f4575937000000").unwrap();
|
||||
let decompressed = "Hello WorldHello WorldHello WorldHello WorldHello World";
|
||||
let mut decoder = GzStreamDecoder::new();
|
||||
let mut decompressed_bytes = vec![];
|
||||
for i in 0..compressed.len() {
|
||||
let b = decoder.update(&compressed[i..i + 1]).unwrap();
|
||||
decompressed_bytes.extend_from_slice(&b);
|
||||
}
|
||||
let last_buffer = decoder.finalize().unwrap();
|
||||
decompressed_bytes.extend_from_slice(&last_buffer);
|
||||
assert_eq!(decompressed, String::from_utf8(decompressed_bytes).unwrap());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_gzip_decompress() {
|
||||
for (compression, message) in vec![
|
||||
(Compression::default(), "Hello World"),
|
||||
(Compression::default(), "Hello WorldHello WorldHello World"),
|
||||
(Compression::default(), "Hello WorldHello WorldHello WorldHello WorldHello World"),
|
||||
(Compression::default(), "Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World"),
|
||||
(Compression::none(), "Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World"),
|
||||
(Compression::fast(), "Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World"),
|
||||
(Compression::best(), "Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World"),
|
||||
] {
|
||||
let mut encoder = GzStreamEncoder::new(compression);
|
||||
let mut compressed_bytes = encoder.update(message.as_bytes()).unwrap();
|
||||
let last_compress_buffer = encoder.finalize().unwrap();
|
||||
compressed_bytes.extend_from_slice(&last_compress_buffer);
|
||||
|
||||
let mut decoder = GzStreamDecoder::new();
|
||||
let mut decompressed_bytes = decoder.update(&compressed_bytes).unwrap();
|
||||
let last_decompress_buffer = decoder.finalize().unwrap();
|
||||
decompressed_bytes.extend_from_slice(&last_decompress_buffer);
|
||||
|
||||
let decompressed_string = String::from_utf8(decompressed_bytes).unwrap();
|
||||
|
||||
assert_eq!(message, decompressed_string.as_str());
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ use crate::cmd_encrypt::CmdEncrypt;
|
||||
use crate::cmd_info::CmdInfo;
|
||||
|
||||
mod util;
|
||||
mod compress;
|
||||
mod config;
|
||||
mod spec;
|
||||
mod crypto;
|
||||
|
||||
Reference in New Issue
Block a user