Skip to main content

crush_parallel/
lib.rs

1//! `crush-parallel` — Parallel DEFLATE compression engine
2//!
3//! Implements a pigz-inspired multi-threaded compression engine using a custom
4//! binary format (CRSH) optimised for parallel decompression and random block access.
5//!
6//! # Quick Start
7//!
8//! ```no_run
9//! use crush_parallel::{compress, decompress, EngineConfiguration};
10//!
11//! let config = EngineConfiguration::default();
12//! let data = b"hello world".repeat(10000);
13//! let compressed = compress(&data, &config).expect("compression failed");
14//! let recovered = decompress(&compressed, &config).expect("decompression failed");
15//! assert_eq!(data.as_slice(), recovered.as_slice());
16//! ```
17
18pub mod block;
19pub mod config;
20pub mod engine;
21pub mod format;
22pub mod index;
23
24// Public API re-exports
25pub use config::{
26    EngineConfiguration, EngineConfigurationBuilder, ProgressCallback, ProgressEvent, ProgressPhase,
27};
28pub use engine::{
29    compress, compress_file, compress_stream, compress_to_writer, decompress,
30    decompress_from_reader,
31};
32pub use format::BlockIndexEntry;
33pub use index::{decompress_block, load_index, BlockIndex};
34
35use crush_core::error::Result;
36use crush_core::plugin::{CompressionAlgorithm, PluginMetadata, COMPRESSION_ALGORITHMS};
37use linkme::distributed_slice;
38use std::sync::atomic::AtomicBool;
39use std::sync::Arc;
40
41/// Magic number for the parallel-deflate plugin in the crush-core outer format.
42///
43/// Format: `[0x43, 0x52, 0x01, plugin_id]` = `"CR"` + version 1 + plugin ID.
44/// Plugin ID 0x00 is reserved for the native deflate plugin; 0x02 identifies
45/// the parallel-deflate engine so `CrushHeader::has_valid_version()` passes.
46pub const PLUGIN_MAGIC: [u8; 4] = [0x43, 0x52, 0x01, 0x02];
47
48/// Crush-parallel plugin implementation registered into the crush-core plugin registry.
49struct ParallelDeflatePlugin;
50
51impl CompressionAlgorithm for ParallelDeflatePlugin {
52    fn name(&self) -> &'static str {
53        "parallel-deflate"
54    }
55
56    fn metadata(&self) -> PluginMetadata {
57        PluginMetadata {
58            name: "parallel-deflate",
59            version: env!("CARGO_PKG_VERSION"),
60            magic_number: PLUGIN_MAGIC,
61            throughput: 500.0,
62            compression_ratio: 0.65,
63            description: "Multi-threaded DEFLATE with CRSH block format; parallel decompress and random access",
64        }
65    }
66
67    fn compress(&self, input: &[u8], cancel_flag: Arc<AtomicBool>) -> Result<Vec<u8>> {
68        use crate::config::ProgressCallback;
69        use std::sync::atomic::Ordering;
70        use std::sync::Mutex;
71
72        // Bridge the crush-core AtomicBool cancel flag into our ProgressCallback.
73        let cb: ProgressCallback = Box::new(move |_event| !cancel_flag.load(Ordering::Acquire));
74        let config = EngineConfiguration::builder()
75            .progress(Arc::new(Mutex::new(cb)))
76            .build()?;
77        compress(input, &config)
78    }
79
80    fn decompress(&self, input: &[u8], cancel_flag: Arc<AtomicBool>) -> Result<Vec<u8>> {
81        use crate::config::ProgressCallback;
82        use std::sync::atomic::Ordering;
83        use std::sync::Mutex;
84
85        let cb: ProgressCallback = Box::new(move |_event| !cancel_flag.load(Ordering::Acquire));
86        let config = EngineConfiguration::builder()
87            .progress(Arc::new(Mutex::new(cb)))
88            .build()?;
89        decompress(input, &config)
90    }
91
92    fn detect(&self, file_header: &[u8]) -> bool {
93        // CRSH files start with the 4-byte magic [0x43, 0x52, 0x53, 0x48] ("CRSH")
94        file_header.len() >= 4 && file_header[0..4] == crate::format::CRSH_MAGIC
95    }
96}
97
98/// Compile-time plugin registration via `linkme` distributed slice.
99#[distributed_slice(COMPRESSION_ALGORITHMS)]
100static PARALLEL_DEFLATE_PLUGIN: &dyn CompressionAlgorithm = &ParallelDeflatePlugin;