lupin 1.0.0

A blazing-fast, lightweight steganography tool for concealing secret data within normal files.
Documentation
# Library Guide

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
lupin = "0.2.1"  # Replace with actual version
```

## Quick Start

```rust
use lupin::operations::{embed, extract};

// Read source and payload
let source_data = std::fs::read("document.pdf")?;
let payload_data = std::fs::read("secret.txt")?;

// Embed with rich metadata
let (embedded_data, embed_result) = embed(&source_data, &payload_data)?;
println!("Embedded {} bytes using {} engine",
         embed_result.payload_size, embed_result.engine);

// Save result
std::fs::write("output.pdf", embedded_data)?;

// Extract later
let output_data = std::fs::read("output.pdf")?;
let (extracted_data, extract_result) = extract(&output_data)?;
std::fs::write("recovered.txt", extracted_data)?;
```

## Core Types

### Operations Module

```rust
use lupin::operations::{embed, extract, EmbedResult, ExtractResult};

// Vector-based operations
pub fn embed(source_data: &[u8], payload_data: &[u8]) -> Result<(Vec<u8>, EmbedResult)>
pub fn extract(source_data: &[u8]) -> Result<(Vec<u8>, ExtractResult)>
```

### Result Types

```rust
#[derive(Debug, Clone)]
pub struct EmbedResult {
    pub source_size: usize,    // Original file size
    pub payload_size: usize,   // Hidden data size
    pub output_size: usize,    // Final file size
    pub engine: String,        // Engine used (e.g., "PDF")
}

#[derive(Debug, Clone)]
pub struct ExtractResult {
    pub source_size: usize,    // Source file size
    pub payload_size: usize,   // Extracted data size
    pub engine: String,        // Engine used
}
```

## Benefits of Vector-based API

- **Performance**: No intermediate file I/O in library operations, making it adaptable to various data sources.
- **Flexibility**: Works with data from any source (files, network, memory, etc.).
- **Testability**: Easy to test with in-memory data.
- **Clean separation**: I/O concerns handled by your application.

## Advanced Examples

### Working with Different Data Sources

```rust
use lupin::operations::{embed, extract};

// From network or any byte source
let source_data = download_pdf_from_url("https://example.com/doc.pdf").await?;
let payload_data = b"secret message".to_vec();

// Embed without touching filesystem
let (result, metadata) = embed(&source_data, &payload_data)?;
println!("Output size: {} bytes (+{:.1}% increase)",
         metadata.output_size,
         (metadata.output_size as f64 / metadata.source_size as f64 - 1.0) * 100.0);

// Stream result anywhere
send_to_storage(&result).await?;
```

### Error Handling

```rust
use lupin::error::LupinError;
use lupin::operations::embed;

let source_data = std::fs::read("document.pdf")?;
let payload_data = std::fs::read("secret.txt")?;

match embed(&source_data, &payload_data) {
    Ok((embedded_data, metadata)) => {
        println!("Success! Used {} engine", metadata.engine);
        std::fs::write("output.pdf", embedded_data)?;
    }
    Err(LupinError::UnsupportedFormat) => {
        eprintln!("File format not supported");
    }
    Err(LupinError::PdfNoEofMarker) => {
        eprintln!("Invalid PDF file");
    }
    Err(e) => {
        eprintln!("Other error: {}", e);
    }
}
```

### Engine System Direct Access

For more control, you can use the engine system directly:

```rust
use lupin::{EngineRouter, SteganographyEngine};

let router = EngineRouter::new();
let data = std::fs::read("document.pdf")?;

// Auto-detect and get the appropriate engine
let engine = router.detect_engine(&data)?;
println!("Detected format: {}", engine.format_name());

// Use the engine directly
let payload = b"secret data";
let result = engine.embed(&data, payload)?;

// Save the embedded data
std::fs::write("embedded.pdf", result)?;
```

### Testing with In-Memory Data

```rust
#[cfg(test)]
mod tests {
    use lupin::operations::{embed, extract};

    #[test]
    fn test_round_trip() {
        // Create minimal PDF
        let pdf_data = b"%PDF-1.4\n%%EOF".to_vec();
        let payload = b"test payload";

        // Embed
        let (embedded, embed_result) = embed(&pdf_data, payload).unwrap();
        assert_eq!(embed_result.engine, "PDF");
        assert_eq!(embed_result.payload_size, payload.len());

        // Extract
        let (extracted, extract_result) = extract(&embedded).unwrap();
        assert_eq!(extracted, payload);
        assert_eq!(extract_result.payload_size, payload.len());
    }
}
```

## Error Types

The full list of error types can always be found in the `lupin::error` module.

```rust
use lupin::error::LupinError;

// Common error types you'll encounter:
LupinError::UnsupportedFormat          // File format not supported
LupinError::PdfNoEofMarker            // Invalid PDF (no %%EOF)
LupinError::PdfNoHiddenData           // No steganographic data found
LupinError::PdfCorruptedData          // Hidden data is corrupted
LupinError::SourceFileRead { path, source }     // CLI: Can't read source file
LupinError::PayloadFileRead { path, source }    // CLI: Can't read payload file
LupinError::OutputFileWrite { path, source }    // CLI: Can't write output file
```