What are the trade-offs between zip::write::FileOptions::compression_method and store for archive creation?

The compression_method option controls whether and how files are compressed in a ZIP archive, with store representing the special case of no compressionβ€”trading compression ratio for speed, memory usage, and compatibility. Choosing between store (no compression) and compression methods like Deflated involves weighing file size reduction against CPU time, memory consumption, and decompression requirements.

Understanding ZIP Compression Methods

use zip::write::FileOptions;
use zip::CompressionMethod;
 
fn compression_methods() {
    // The zip crate supports multiple compression methods:
    
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Method              β”‚ Compression β”‚ Speed    β”‚ Memory     β”‚ Support  β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Store               β”‚ None        β”‚ Fastest  β”‚ Minimal    β”‚ Universalβ”‚
    // β”‚ Deflate             β”‚ Moderate    β”‚ Fast     β”‚ Low        β”‚ Universalβ”‚
    // β”‚ Deflate64           β”‚ High        β”‚ Medium   β”‚ Low        β”‚ Limited  β”‚
    // β”‚ Bzip2               β”‚ High        β”‚ Slow     β”‚ Medium     β”‚ Common   β”‚
    // β”‚ Zstd                β”‚ Very High   β”‚ Fast     β”‚ Medium     β”‚ Modern   β”‚
    // β”‚ Xz                  β”‚ Very High   β”‚ Slow     β”‚ Medium     β”‚ Modern   β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Store: No compression, files stored as-is
    // Deflate: Standard ZIP compression (most common)
    // Others: Higher compression ratios, varying support
}

ZIP archives support multiple compression methods with different trade-offs.

Store: No Compression

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn store_method() {
    // Store means: write file data exactly as-is
    // No compression applied, no decompression needed
    
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    
    // Use store (no compression)
    let options = FileOptions::default()
        .compression_method(CompressionMethod::Stored);
    
    zip.start_file("data.bin", options.clone()).unwrap();
    zip.write_all(b"raw data").unwrap();
    
    zip.finish().unwrap();
    
    // The file "data.bin" is stored exactly as written
    // Archive size β‰ˆ file size + ZIP overhead
}

CompressionMethod::Stored writes files without any compression.

Deflate: Standard Compression

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn deflate_method() {
    // Deflate is the most common ZIP compression
    // Balances compression ratio and speed
    
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    
    // Use deflate compression
    let options = FileOptions::default()
        .compression_method(CompressionMethod::Deflated);
    
    zip.start_file("data.txt", options.clone()).unwrap();
    zip.write_all(b"This text will be compressed and take less space").unwrap();
    
    zip.finish().unwrap();
    
    // Deflate compresses text/data efficiently
    // Archive size < original file size
}

CompressionMethod::Deflated applies the standard DEFLATE algorithm.

File Size Trade-offs

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn size_comparison() {
    // Compare archive sizes for different content types:
    
    let text_data = "Hello, World! ".repeat(1000);  // ~14KB of repeating text
    let random_data: Vec<u8> = (0..14000).map(|i| (i % 256) as u8).collect();
    let already_compressed = include_bytes!("some_file.zip").to_vec();
    
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Content Type        β”‚ Store    β”‚ Deflate  β”‚ Deflate64 β”‚ Zstd          β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Text (repetitive)   β”‚ 14KB     β”‚ ~0.5KB   β”‚ ~0.4KB    β”‚ ~0.3KB        β”‚
    // β”‚ Random data         β”‚ 14KB     β”‚ ~14KB    β”‚ ~14KB     β”‚ ~14KB         β”‚
    // β”‚ Already compressed  β”‚ size     β”‚ size+    β”‚ size++    β”‚ size+         β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Key insight: Compression effectiveness depends on data entropy
    // - High entropy (random): compression adds overhead
    // - Low entropy (text): compression saves significant space
    // - Pre-compressed: re-compression usually increases size
}
 
fn demonstrating_size_differences() {
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    
    // Repetitive text compresses well
    let text = "AAAAAAAAAA".repeat(1000);  // 10KB of 'A'
    
    let stored_options = FileOptions::default()
        .compression_method(CompressionMethod::Stored);
    let deflated_options = FileOptions::default()
        .compression_method(CompressionMethod::Deflated);
    
    // Store: ~10KB in archive
    zip.start_file("stored.txt", stored_options).unwrap();
    zip.write_all(text.as_bytes()).unwrap();
    
    // Deflate: ~bytes in archive (high compression)
    zip.start_file("deflated.txt", deflated_options).unwrap();
    zip.write_all(text.as_bytes()).unwrap();
    
    zip.finish().unwrap();
}

Compression effectiveness varies dramatically based on data entropy.

CPU Time and Performance

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
use std::time::Instant;
 
fn performance_comparison() {
    let large_data: Vec<u8> = (0..10_000_000).map(|i| (i % 256) as u8).collect();
    
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Operation     β”‚ Store           β”‚ Deflate         β”‚ Bzip2           β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Compression   β”‚ Copy only       β”‚ CPU work       β”‚ Heavy CPU work  β”‚
    // β”‚ Decompression β”‚ Copy only       β”‚ CPU work       β”‚ Heavy CPU work  β”‚
    // β”‚ Memory        β”‚ Buffer only     β”‚ Dictionary     β”‚ Larger tables   β”‚
    // β”‚ Throughput    β”‚ Disk speed      β”‚ CPU bound      β”‚ CPU bound       β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Store: I/O bound, not CPU bound
    let start = Instant::now();
    {
        let file = File::create("stored.zip").unwrap();
        let mut zip = ZipWriter::new(file);
        let options = FileOptions::default()
            .compression_method(CompressionMethod::Stored);
        zip.start_file("data.bin", options).unwrap();
        zip.write_all(&large_data).unwrap();
        zip.finish().unwrap();
    }
    let store_time = start.elapsed();
    
    // Deflate: CPU bound for compressible data
    let start = Instant::now();
    {
        let file = File::create("deflated.zip").unwrap();
        let mut zip = ZipWriter::new(file);
        let options = FileOptions::default()
            .compression_method(CompressionMethod::Deflated);
        zip.start_file("data.bin", options).unwrap();
        zip.write_all(&large_data).unwrap();
        zip.finish().unwrap();
    }
    let deflate_time = start.elapsed();
    
    // Store is faster for:
    // - Already compressed data
    // - High-entropy data (won't compress anyway)
    // - Fast storage where size doesn't matter
    
    // Deflate overhead is worth it for:
    // - Compressible data (text, structured data)
    // - Network transfer (bandwidth > CPU)
    // - Storage-constrained environments
}

CPU cost varies significantly; store has minimal overhead, compression adds CPU work.

Memory Usage Differences

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
 
fn memory_comparison() {
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Method     β”‚ Compression Memory β”‚ Decompression Memory β”‚ Notes       β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Store      β”‚ Minimal           β”‚ Minimal              β”‚ Just buffersβ”‚
    // β”‚ Deflate    β”‚ Low (~300KB)      β”‚ Low (~50KB)          β”‚ Dictionary β”‚
    // β”‚ Deflate64  β”‚ Moderate          β”‚ Moderate             β”‚ Larger dict β”‚
    // β”‚ Bzip2      β”‚ Moderate (~1MB)   β”‚ Moderate (~1MB)      β”‚ Block sort β”‚
    // β”‚ Zstd       β”‚ Configurable      β”‚ Low                  β”‚ Window sizeβ”‚
    // β”‚ Xz         β”‚ Higher            β”‚ Higher               β”‚ LZMA dict  β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Store uses the least memory:
    // - No compression buffers
    // - No decompression state
    // - Simple byte copying
    
    // Compression methods require:
    // - Compression dictionary/window
    // - Algorithm state
    // - Working buffers
    
    // For memory-constrained systems, store is preferred
}

Compression methods require additional memory for dictionaries and algorithm state.

Compatibility and Support

use zip::CompressionMethod;
 
fn compatibility_comparison() {
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Method     β”‚ ZIP Support        β”‚ OS Support          β”‚ Tool Support  β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Store      β”‚ Universal          β”‚ Universal           β”‚ Universal     β”‚
    // β”‚ Deflate    β”‚ Universal          β”‚ Universal           β”‚ Universal     β”‚
    // β”‚ Deflate64  β”‚ Limited            β”‚ Windows preferred   β”‚ Limited       β”‚
    // β”‚ Bzip2      β”‚ Common             β”‚ Unix common         β”‚ Common        β”‚
    // β”‚ Zstd       β”‚ Modern             β”‚ Requires library    β”‚ Limited       β”‚
    // β”‚ Xz         β”‚ Modern             β”‚ Requires library    β”‚ Limited       β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Store and Deflate are universally supported:
    // - All ZIP tools understand them
    // - All operating systems handle them
    // - No special libraries needed
    
    // When to use Store for compatibility:
    // - Archives for unknown/untrusted extractors
    // - Maximum compatibility required
    // - Embedded systems with limited libraries
    
    // When Deflate is safe:
    // - Standard desktop environments
    // - Most modern ZIP tools
    // - Web distribution (browsers handle it)
}

Store and Deflate have universal support; other methods vary.

When to Use Store (No Compression)

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn when_to_use_store() {
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Use Store When:                                                         β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ 1. Files are already compressed (images, videos, other archives)       β”‚
    // β”‚ 2. Compression overhead > space savings (random data, encrypted data)  β”‚
    // β”‚ 3. CPU time is precious (embedded, mobile, battery-constrained)        β”‚
    // β”‚ 4. Memory is limited (embedded systems, large file counts)             β”‚
    // β”‚ 5. Maximum compatibility required (unknown extraction environments)     β”‚
    // β”‚ 6. Real-time archive creation (minimize latency)                        β”‚
    // β”‚ 7. Temporary archives (short-lived, not worth compressing)              β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    let options = FileOptions::default()
        .compression_method(CompressionMethod::Stored);
    
    // Already compressed files - no benefit from re-compression
    let jpg_data = include_bytes!("image.jpg");
    zip.start_file("photo.jpg", options.clone()).unwrap();
    zip.write_all(jpg_data).unwrap();
    
    let mp4_data = include_bytes!("video.mp4");
    zip.start_file("video.mp4", options.clone()).unwrap();
    zip.write_all(mp4_data).unwrap();
    
    // Encrypted data - appears random, won't compress
    let encrypted_data = vec![0x42; 1000];  // Simulated encrypted
    zip.start_file("encrypted.bin", options.clone()).unwrap();
    zip.write_all(&encrypted_data).unwrap();
    
    zip.finish().unwrap();
}

Store is optimal when compression would add overhead without benefit.

When to Use Compression

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn when_to_use_compression() {
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Use Compression When:                                                   β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ 1. Text files (logs, code, documentation)                                β”‚
    // β”‚ 2. Structured data (JSON, XML, CSV)                                    β”‚
    // β”‚ 3. Databases and binary data (often compressible)                       β”‚
    // β”‚ 4. Network transfer (bandwidth > CPU cost)                             β”‚
    // β”‚ 5. Storage costs are high (cloud storage, SSD)                         β”‚
    // β”‚ 6. Long-term archival (storage savings over time)                       β”‚
    // β”‚ 7. Distribution archives (download bandwidth savings)                   β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    let options = FileOptions::default()
        .compression_method(CompressionMethod::Deflated);
    
    // Text files compress well
    let log_data = "Log entry repeated many times... ".repeat(100);
    zip.start_file("logs/app.log", options.clone()).unwrap();
    zip.write_all(log_data.as_bytes()).unwrap();
    
    // JSON compresses well (repetitive structure)
    let json_data = r#"{"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}"#;
    zip.start_file("data/users.json", options.clone()).unwrap();
    zip.write_all(json_data.as_bytes()).unwrap();
    
    // Source code compresses well
    let code = include_str!("main.rs");
    zip.start_file("src/main.rs", options.clone()).unwrap();
    zip.write_all(code.as_bytes()).unwrap();
    
    zip.finish().unwrap();
}

Compression is beneficial when files have low entropy and size reduction matters.

Mixed Compression Strategies

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn mixed_compression_strategy() {
    // Best practice: use different compression per file type
    
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    
    let stored = FileOptions::default()
        .compression_method(CompressionMethod::Stored);
    let deflated = FileOptions::default()
        .compression_method(CompressionMethod::Deflated);
    
    // Text files: compress
    zip.start_file("README.md", deflated.clone()).unwrap();
    zip.write_all(b"# Documentation\n\nThis is compressible text...").unwrap();
    
    // Source code: compress
    zip.start_file("src/main.rs", deflated.clone()).unwrap();
    zip.write_all(b"fn main() { println!(\"Hello\"); }").unwrap();
    
    // Already compressed: store
    zip.start_file("image.png", stored.clone()).unwrap();
    zip.write_all(&[0x89, 0x50, 0x4E, 0x47]).unwrap();  // PNG header
    
    // Large binary with unknown compressibility: compress
    zip.start_file("data.bin", deflated.clone()).unwrap();
    zip.write_all(&[0u8; 1000]).unwrap();
    
    zip.finish().unwrap();
    
    // This approach:
    // - Compresses where it helps
    // - Avoids where it hurts (already compressed)
    // - Balances overall archive size and creation time
}

Mixing compression methods per-file optimizes the overall archive.

Compression Level Considerations

use zip::write::FileOptions;
use zip::CompressionMethod;
 
fn compression_levels() {
    // Deflate supports compression levels (1-9, or using defaults)
    
    // Higher compression levels:
    // - Smaller output files
    // - More CPU time during compression
    // - Same decompression speed (mostly)
    
    // The zip crate typically uses default compression level
    // Custom levels may require additional configuration
    
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Level β”‚ Compression Time β”‚ Size      β”‚ Decompression Time β”‚ Use Case β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ 1     β”‚ Fast             β”‚ Larger    β”‚ Same               β”‚ Real-timeβ”‚
    // β”‚ 6     β”‚ Balanced (default)β”‚ Balanced β”‚ Same               β”‚ General  β”‚
    // β”‚ 9     β”‚ Slow             β”‚ Smallest β”‚ Same               β”‚ Archive  β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Note: Decompression speed is relatively constant across levels
    // Only compression time varies significantly
}

Compression level trades creation time for file size; decompression is consistent.

Real-World Decision Framework

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
use std::path::Path;
 
fn choose_compression_method(file_path: &Path, content_type: ContentType) -> CompressionMethod {
    // Decision framework based on content type
    match content_type {
        // Already compressed - use store
        ContentType::Image
        | ContentType::Video
        | ContentType::Audio
        | ContentType::Archive => CompressionMethod::Stored,
        
        // Highly compressible - use deflate
        ContentType::Text
        | ContentType::SourceCode
        | ContentType::Json
        | ContentType::Xml => CompressionMethod::Deflated,
        
        // Unknown - compress to check (deflate has low overhead if incompressible)
        ContentType::Unknown => CompressionMethod::Deflated,
        
        // Binary - might compress well
        ContentType::Binary => CompressionMethod::Deflated,
    }
}
 
enum ContentType {
    Text,
    SourceCode,
    Json,
    Xml,
    Image,
    Video,
    Audio,
    Archive,
    Binary,
    Unknown,
}
 
// Or decide based on file extension:
fn compression_by_extension(path: &Path) -> CompressionMethod {
    let ext = path.extension()
        .and_then(|e| e.to_str())
        .unwrap_or("");
    
    match ext.to_lowercase().as_str() {
        // Already compressed formats
        "jpg" | "jpeg" | "png" | "gif" | "webp" | "bmp" => CompressionMethod::Stored,
        "mp4" | "avi" | "mkv" | "webm" => CompressionMethod::Stored,
        "mp3" | "ogg" | "flac" | "aac" => CompressionMethod::Stored,
        "zip" | "gz" | "bz2" | "xz" | "7z" => CompressionMethod::Stored,
        
        // Compressible formats
        "txt" | "md" | "rst" | "html" | "css" => CompressionMethod::Deflated,
        "json" | "xml" | "yaml" | "toml" => CompressionMethod::Deflated,
        "rs" | "py" | "js" | "go" | "java" => CompressionMethod::Deflated,
        "csv" | "tsv" => CompressionMethod::Deflated,
        
        // Default to deflate for unknown
        _ => CompressionMethod::Deflated,
    }
}

Use file type detection to automatically choose compression method.

Decompression Speed Considerations

use zip::CompressionMethod;
 
fn decompression_speed() {
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Method     β”‚ Decompression Speed β”‚ Memory Usage β”‚ CPU Usage           β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Store      β”‚ Disk I/O speed      β”‚ Minimal      β”‚ Zero                β”‚
    // β”‚ Deflate    β”‚ Very fast           β”‚ Low          β”‚ Low                 β”‚
    // β”‚ Deflate64  β”‚ Fast                β”‚ Low          β”‚ Low                 β”‚
    // β”‚ Bzip2      β”‚ Medium              β”‚ Medium       β”‚ Medium              β”‚
    // β”‚ Zstd       β”‚ Fast                β”‚ Low         β”‚ Low                 β”‚
    // β”‚ Xz         β”‚ Slow                β”‚ Higher       β”‚ Higher              β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Store decompression is trivial: copy bytes
    // Deflate decompression is fast: well-optimized, low overhead
    // Higher compression methods: more work to decompress
    
    // For distribution archives (many downloads, one extraction each):
    // - Compression savings multiply across downloads
    // - Decompression speed matters per user
    
    // For frequently accessed archives:
    // - Decompression speed matters more
    // - Store may be better for frequently-read files
}

Store has the fastest decompression; compressed files require CPU work.

Complete Summary

use zip::write::{FileOptions, ZipWriter};
use zip::CompressionMethod;
use std::io::Write;
use std::fs::File;
 
fn complete_summary() {
    // β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    // β”‚ Factor        β”‚ Store                  β”‚ Deflate/Compressed           β”‚
    // β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    // β”‚ Size          β”‚ No reduction           β”‚ 30-90% reduction typical     β”‚
    // β”‚ Creation time β”‚ Fastest (I/O bound)   β”‚ Slower (CPU bound)           β”‚
    // β”‚ Extraction    β”‚ Fastest (copy)         β”‚ Fast (optimized)            β”‚
    // β”‚ Memory        β”‚ Minimal                β”‚ Dictionary overhead         β”‚
    // β”‚ Compatibility β”‚ Universal              β”‚ Universal (deflate)          β”‚
    // β”‚ Best for      β”‚ Pre-compressed, random β”‚ Text, structured, unknown   β”‚
    // β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    
    // Decision tree:
    // 1. Is data already compressed? β†’ Store
    // 2. Is data high-entropy (random)? β†’ Store
    // 3. Is CPU/memory limited? β†’ Store
    // 4. Is compatibility critical? β†’ Store or Deflate
    // 5. Is data text/structured? β†’ Deflate
    // 6. Is storage/bandwidth expensive? β†’ Deflate
    // 7. Unknown data type? β†’ Deflate (low overhead if incompressible)
    
    // Common patterns:
    let file = File::create("archive.zip").unwrap();
    let mut zip = ZipWriter::new(file);
    
    // Pattern 1: All store (for pre-compressed content)
    // let options = FileOptions::default()
    //     .compression_method(CompressionMethod::Stored);
    
    // Pattern 2: All deflate (for text/code archives)
    // let options = FileOptions::default()
    //     .compression_method(CompressionMethod::Deflated);
    
    // Pattern 3: Mixed (best overall)
    // Use Stored for: jpg, png, mp4, mp3, zip, gz, etc.
    // Use Deflated for: txt, md, rs, json, xml, csv, etc.
    
    // The zip crate's default is typically Deflated for most use cases
}
 
// Key insight:
// The trade-off between Store and compression methods is fundamentally
// about CPU/memory cost vs storage/bandwidth cost. Store is optimal
// when files won't compress (already compressed, encrypted, random) or
// when CPU/memory constraints dominate. Deflate is optimal when files
// compress well (text, code, structured data) and storage/bandwidth
// matters more than compression time. For decompression, Store is
// fastest (just copying bytes) while Deflate remains fast due to
// decades of optimization. The best practice is often mixed: Store
// for pre-compressed files, Deflate for compressible content. The
// zip crate's FileOptions::compression_method() sets this per-file,
// allowing optimal compression choices based on file type.

Key insight: The choice between Store and compression methods like Deflate is a trade-off between computational cost and storage savings. Store (no compression) is optimal when files are already compressed, have high entropy (random/encrypted data), or when CPU/memory constraints matter more than size. Deflate is optimal for compressible content (text, code, structured data) where the 30-90% size reduction outweighs compression overhead. The best practice is often a mixed strategy: use Store for pre-compressed files (images, videos, existing archives) and Deflate for compressible files (text, source code, JSON). Decompression speed favors Store (zero CPU work), but Deflate decompression is well-optimized and typically acceptable. Compatibility favors both Store and Deflate as universally supported ZIP methods.