use std::env;
use structured_zstd::encoding::{
CompressionLevel, CompressionParameters, FrameCompressor, Strategy,
};
fn body(len: usize) -> Vec<u8> {
let mut bytes = Vec::with_capacity(len);
let mut counter = 0u32;
while bytes.len() < len {
let line = format!(
"ts=2026-03-26T21:39:{:02}Z level=INFO msg=\"flush memtable\" seq={counter} \
tenant=demo table=orders region=eu-west\n",
counter % 60,
);
let remaining = len - bytes.len();
bytes.extend_from_slice(&line.as_bytes()[..line.len().min(remaining)]);
counter += 1;
}
bytes
}
fn main() {
let args: Vec<String> = env::args().collect();
let window_log: u32 = args.get(1).and_then(|s| s.parse().ok()).unwrap_or(10);
let hash_log: u32 = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(20);
let frame_bytes: usize = args
.get(3)
.and_then(|s| s.parse().ok())
.unwrap_or(4 * 1024 * 1024);
let iters: u32 = args.get(4).and_then(|s| s.parse().ok()).unwrap_or(4);
let dict_path: Option<&str> = args.get(5).map(|s| s.as_str());
let src = body(frame_bytes);
let params = CompressionParameters::builder(CompressionLevel::Level(1))
.strategy(Strategy::Fast)
.window_log(window_log)
.hash_log(hash_log)
.build()
.expect("parameters within bounds");
let mut cctx: FrameCompressor = FrameCompressor::new(CompressionLevel::Level(1));
cctx.set_parameters(¶ms);
if let Some(path) = dict_path {
let dict = std::fs::read(path).expect("read dict file");
cctx.set_dictionary_from_bytes(&dict)
.expect("dictionary should attach");
}
let mut out: Vec<u8> = Vec::new();
let mut sink: usize = 0;
for _ in 0..iters {
cctx.compress_independent_frame_into(&src, &mut out);
sink = sink.wrapping_add(out.len());
core::hint::black_box(&out);
}
let mode = if dict_path.is_some() {
"dictionary"
} else {
"capped"
};
eprintln!(
"mode={mode} windowLog={window_log} hashLog={hash_log} frame={frame_bytes} \
iters={iters} dict={} out={} sum={sink} heap={}",
dict_path.unwrap_or("none"),
out.len(),
cctx.heap_size(),
);
}