use super::byte_utils::bytes_from_i64_slice;
use crate::marshal::{register_typed_fn_1, register_typed_fn_2};
use crate::module_exports::ModuleExports;
use crate::typed_module_exports::{ConcreteReturn, ConcreteType, TypedReturn};
use std::sync::Arc;
pub fn create_compress_module() -> ModuleExports {
let mut module = ModuleExports::new("std::core::compress");
module.description = "Data compression and decompression (gzip, zstd, deflate)".to_string();
register_typed_fn_1::<_, Arc<String>>(
&mut module,
"gzip",
"Compress a string using gzip, returning a byte array",
"data",
"string",
ConcreteType::Bytes,
|data, _ctx| {
use flate2::Compression;
use flate2::write::GzEncoder;
use std::io::Write;
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder
.write_all(data.as_bytes())
.map_err(|e| format!("compress.gzip() failed: {}", e))?;
let compressed = encoder
.finish()
.map_err(|e| format!("compress.gzip() failed: {}", e))?;
Ok(TypedReturn::Concrete(ConcreteReturn::Bytes(compressed)))
},
);
register_typed_fn_1::<_, Vec<i64>>(
&mut module,
"gunzip",
"Decompress a gzip byte array back to a string",
"data",
"Array<int>",
ConcreteType::String,
|data, _ctx| {
use flate2::read::GzDecoder;
use std::io::Read;
let bytes = bytes_from_i64_slice(&data)
.map_err(|e| format!("compress.gunzip(): {}", e))?;
let mut decoder = GzDecoder::new(&bytes[..]);
let mut output = String::new();
decoder
.read_to_string(&mut output)
.map_err(|e| format!("compress.gunzip() failed: {}", e))?;
Ok(TypedReturn::Concrete(ConcreteReturn::String(output)))
},
);
register_typed_fn_2::<_, Arc<String>, i64>(
&mut module,
"zstd",
"Compress a string using Zstandard, returning a byte array",
[("data", "string"), ("level", "int")],
ConcreteType::Bytes,
|data, level, _ctx| {
let compressed = zstd::encode_all(data.as_bytes(), level as i32)
.map_err(|e| format!("compress.zstd() failed: {}", e))?;
Ok(TypedReturn::Concrete(ConcreteReturn::Bytes(compressed)))
},
);
register_typed_fn_1::<_, Vec<i64>>(
&mut module,
"unzstd",
"Decompress a Zstandard byte array back to a string",
"data",
"Array<int>",
ConcreteType::String,
|data, _ctx| {
let bytes = bytes_from_i64_slice(&data)
.map_err(|e| format!("compress.unzstd(): {}", e))?;
let decompressed = zstd::decode_all(&bytes[..])
.map_err(|e| format!("compress.unzstd() failed: {}", e))?;
let output = String::from_utf8(decompressed)
.map_err(|e| format!("compress.unzstd() invalid UTF-8: {}", e))?;
Ok(TypedReturn::Concrete(ConcreteReturn::String(output)))
},
);
register_typed_fn_1::<_, Arc<String>>(
&mut module,
"deflate",
"Compress a string using raw deflate, returning a byte array",
"data",
"string",
ConcreteType::Bytes,
|data, _ctx| {
use flate2::Compression;
use flate2::write::DeflateEncoder;
use std::io::Write;
let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default());
encoder
.write_all(data.as_bytes())
.map_err(|e| format!("compress.deflate() failed: {}", e))?;
let compressed = encoder
.finish()
.map_err(|e| format!("compress.deflate() failed: {}", e))?;
Ok(TypedReturn::Concrete(ConcreteReturn::Bytes(compressed)))
},
);
register_typed_fn_1::<_, Vec<i64>>(
&mut module,
"inflate",
"Decompress a raw deflate byte array back to a string",
"data",
"Array<int>",
ConcreteType::String,
|data, _ctx| {
use flate2::read::DeflateDecoder;
use std::io::Read;
let bytes = bytes_from_i64_slice(&data)
.map_err(|e| format!("compress.inflate(): {}", e))?;
let mut decoder = DeflateDecoder::new(&bytes[..]);
let mut output = String::new();
decoder
.read_to_string(&mut output)
.map_err(|e| format!("compress.inflate() failed: {}", e))?;
Ok(TypedReturn::Concrete(ConcreteReturn::String(output)))
},
);
module
}