Compress with a custom block size (useful for testing or tuning).
(data: &[u8], block_size: usize)
| 38 | |
| 39 | /// Compress with a custom block size (useful for testing or tuning). |
| 40 | pub fn encode_with_block_size(data: &[u8], block_size: usize) -> Vec<u8> { |
| 41 | let block_size = block_size.max(64); // minimum 64 bytes |
| 42 | let block_count = if data.is_empty() { |
| 43 | 0 |
| 44 | } else { |
| 45 | data.len().div_ceil(block_size) |
| 46 | }; |
| 47 | |
| 48 | // Pre-allocate: header(12) + block_lengths(4*N) + compressed_blocks. |
| 49 | let mut out = Vec::with_capacity(12 + block_count * 4 + data.len()); |
| 50 | |
| 51 | // Header. |
| 52 | out.extend_from_slice(&(data.len() as u32).to_le_bytes()); |
| 53 | out.extend_from_slice(&(block_size as u32).to_le_bytes()); |
| 54 | out.extend_from_slice(&(block_count as u32).to_le_bytes()); |
| 55 | |
| 56 | // Reserve space for block length table (filled in after compression). |
| 57 | let lengths_offset = out.len(); |
| 58 | out.resize(lengths_offset + block_count * 4, 0); |
| 59 | |
| 60 | // Compress each block. |
| 61 | for (i, chunk) in data.chunks(block_size).enumerate() { |
| 62 | let compressed = lz4_flex::compress_prepend_size(chunk); |
| 63 | let compressed_len = compressed.len() as u32; |
| 64 | |
| 65 | // Write block length into the table. |
| 66 | let table_pos = lengths_offset + i * 4; |
| 67 | out[table_pos..table_pos + 4].copy_from_slice(&compressed_len.to_le_bytes()); |
| 68 | |
| 69 | // Append compressed block. |
| 70 | out.extend_from_slice(&compressed); |
| 71 | } |
| 72 | |
| 73 | out |
| 74 | } |
| 75 | |
| 76 | /// Decompress LZ4 block-compressed bytes back to raw data. |
| 77 | pub fn decode(data: &[u8]) -> Result<Vec<u8>, CodecError> { |