shoco 0.1.0

Shoco port to Rust, a fast compressor for short strings
Documentation
use std::env;
use std::io::{self, Read, Write};

fn main() {
    let arguments: Vec<String> = env::args().collect();

    if arguments.len() < 2 {
        print_usage(&arguments[0]);
        return;
    }

    match arguments[1].as_str() {
        "-c" | "--compress" => {
            if arguments.len() > 2 {
                let input_text = arguments[2..].join(" ");
                let compressed = shoco::compress_str(&input_text);
                io::stdout().write_all(&compressed).unwrap();
            } else {
                let mut stdin_bytes = Vec::new();
                io::stdin().read_to_end(&mut stdin_bytes).unwrap();
                let compressed = shoco::compress(&stdin_bytes);
                io::stdout().write_all(&compressed).unwrap();
            }
        }
        "-d" | "--decompress" => {
            let mut stdin_bytes = Vec::new();
            io::stdin().read_to_end(&mut stdin_bytes).unwrap();
            match shoco::decompress(&stdin_bytes) {
                Some(decompressed) => {
                    io::stdout().write_all(&decompressed).unwrap();
                }
                None => {
                    eprintln!("Error: Failed to decompress input");
                    std::process::exit(1);
                }
            }
        }
        "-t" | "--test" => {
            let input_text = if arguments.len() > 2 {
                arguments[2..].join(" ")
            } else {
                "hello world".to_string()
            };

            let original_bytes = input_text.as_bytes();
            let compressed = shoco::compress(original_bytes);
            let decompressed = shoco::decompress(&compressed).unwrap();
            let compression_ratio = (compressed.len() as f64 / original_bytes.len() as f64) * 100.0;

            println!("Original:       {:?}", input_text);
            println!("Original len:   {} bytes", original_bytes.len());
            println!("Compressed:     {:?}", compressed);
            println!("Compressed len: {} bytes", compressed.len());
            println!("Ratio:          {:.1}%", compression_ratio);
            println!("Decompressed:   {:?}", String::from_utf8_lossy(&decompressed));
            println!("Roundtrip OK:   {}", original_bytes == decompressed.as_slice());
        }
        "-h" | "--help" => {
            print_usage(&arguments[0]);
        }
        unknown => {
            eprintln!("Unknown option: {}", unknown);
            print_usage(&arguments[0]);
            std::process::exit(1);
        }
    }
}

fn print_usage(program_name: &str) {
    eprintln!("shoco - A fast compressor for short strings");
    eprintln!();
    eprintln!("Usage:");
    eprintln!("  {} -c [STRING]     Compress STRING (or stdin if no STRING)", program_name);
    eprintln!("  {} -d              Decompress stdin", program_name);
    eprintln!("  {} -t [STRING]     Test roundtrip compression", program_name);
    eprintln!("  {} -h              Show this help", program_name);
    eprintln!();
    eprintln!("Examples:");
    eprintln!("  {} -c hello world", program_name);
    eprintln!("  echo 'hello world' | {} -c | {} -d", program_name, program_name);
    eprintln!("  {} -t 'The quick brown fox'", program_name);
}