Skip to main content

streaming_decrypt

Function streaming_decrypt 

Source
pub fn streaming_decrypt<F>(
    data_map: &DataMap,
    get_chunk_parallel: F,
) -> Result<DecryptionStream<F>>
where F: Fn(&[(usize, XorName)]) -> Result<Vec<(usize, Bytes)>>,
Expand description

Creates a streaming decrypt iterator that yields decrypted chunks as Bytes.

This function provides memory-efficient decryption by processing chunks in batches and yielding them one at a time. It’s ideal for large files where loading the entire decrypted content into memory at once would be impractical.

The returned DecryptionStream struct supports both sequential iteration and random access to any byte range within the encrypted file.

§Arguments

  • data_map - The data map containing chunk information
  • get_chunk_parallel - A function that retrieves chunks in parallel given chunk hashes

§Returns

  • Result<DecryptionStream<F>> - An iterator that yields Result<Bytes> for each decrypted chunk

§Examples

§Sequential Processing

use self_encryption::{streaming_decrypt, encrypt, test_helpers::random_bytes, hash::content_hash};
use bytes::Bytes;
use xor_name::XorName;
use std::collections::HashMap;

// Create some test data and encrypt it
let original_data = random_bytes(10000);
let (data_map, encrypted_chunks) = encrypt(original_data)?;

// Create a simple storage backend
let mut storage = HashMap::new();
for chunk in encrypted_chunks {
    let hash = content_hash(&chunk.content);
    storage.insert(hash, chunk.content.to_vec());
}

// Create chunk retrieval function
let get_chunks = |hashes: &[(usize, XorName)]| -> self_encryption::Result<Vec<(usize, Bytes)>> {
    let mut results = Vec::new();
    for &(index, hash) in hashes {
        if let Some(data) = storage.get(&hash) {
            results.push((index, Bytes::from(data.clone())));
        }
    }
    Ok(results)
};

// Create streaming decrypt iterator
let stream = streaming_decrypt(&data_map, get_chunks)?;

// Process each decrypted chunk sequentially
for chunk_result in stream {
    match chunk_result {
        Ok(chunk_bytes) => {
            println!("Decrypted chunk of {} bytes", chunk_bytes.len());
        }
        Err(e) => {
            eprintln!("Error decrypting chunk: {}", e);
            break;
        }
    }
}

§Random Access

use self_encryption::{streaming_decrypt, encrypt, test_helpers::random_bytes, hash::content_hash};
use bytes::Bytes;
use xor_name::XorName;
use std::collections::HashMap;

let original_data = random_bytes(10000);
let (data_map, encrypted_chunks) = encrypt(original_data)?;

let mut storage = HashMap::new();
for chunk in encrypted_chunks {
    let hash = content_hash(&chunk.content);
    storage.insert(hash, chunk.content.to_vec());
}

let get_chunks = |hashes: &[(usize, XorName)]| -> self_encryption::Result<Vec<(usize, Bytes)>> {
    let mut results = Vec::new();
    for &(index, hash) in hashes {
        if let Some(data) = storage.get(&hash) {
            results.push((index, Bytes::from(data.clone())));
        }
    }
    Ok(results)
};

let stream = streaming_decrypt(&data_map, get_chunks)?;

// Random access examples
let chunk_bytes = stream.range(1000..2000)?;
println!("Decrypted range 1000-2000: {} bytes", chunk_bytes.len());

let from_middle = stream.range_from(5000)?;
println!("From byte 5000 to end: {} bytes", from_middle.len());

let first_kilobyte = stream.range_to(1024)?;
println!("First 1024 bytes: {} bytes", first_kilobyte.len());

// Direct range access with get_range
let specific_range = stream.get_range(2000, 500)?;
println!("500 bytes starting at position 2000: {} bytes", specific_range.len());