Skip to main content

PatchSource

Trait PatchSource 

Source
pub trait PatchSource {
    // Required method
    fn read(
        &mut self,
        patch: PatchIndex,
        offset: u64,
        dst: &mut [u8],
    ) -> Result<()>;
}
Expand description

Source of patch-file bytes for an IndexApplier.

Implementations must fill dst completely with dst.len() source bytes starting at offset in the patch identified by patch. A short read — fewer than dst.len() bytes available — must surface as IndexError::PatchSourceTooShort, not as a partial fill. An out-of-range patch must surface as IndexError::PatchIndexOutOfRange.

§Async usage

PatchSource is intentionally synchronous. The indexed-apply driver is dominated by DEFLATE decompression and filesystem syscalls — both fundamentally blocking workloads — and keeping the trait sync lets the crate stay trivially embeddable in either a sync binary or an async runtime without dragging a runtime dependency into every consumer.

Async callers (e.g. a tokio-based launcher) drive the apply by parking the whole IndexApplier::execute call on a blocking-pool thread:

// pseudo-code; the crate has no tokio dependency
let result = tokio::task::spawn_blocking(move || {
    applier.execute(&mut my_patch_source)
}).await?;

Implementors whose backing storage is itself async (e.g. an in-progress download from an axum / reqwest task) can satisfy the sync trait by blocking on a channel against a separate async task that performs the I/O: each PatchSource::read call sends a (patch, offset, len) request to the async side and blocks on the response. Because read is called from inside the spawn_blocking thread the driver lives on, blocking on a channel does not stall the runtime’s reactor.

Required Methods§

Source

fn read(&mut self, patch: PatchIndex, offset: u64, dst: &mut [u8]) -> Result<()>

Fill dst with dst.len() source bytes starting at offset in the patch indexed by patch.

§Errors

Implementors§