Skip to main content

Module apply

Module apply 

Source
Expand description

Filesystem application of parsed chunks (Apply, ApplyContext). Filesystem application of parsed ZiPatch chunks.

§Parse / apply separation

The crate is intentionally split into two independent layers:

  • Parsing (src/chunk/) — reads the binary wire format and produces Chunk values. Nothing in the parser allocates file handles, stats paths, or performs I/O against the install tree.
  • Applying (this module) — takes a stream of Chunk values and writes the patch changes to disk.

The only bridge between the two layers is the Apply trait, which every chunk type implements. Callers that only need to inspect patch contents can use the parser without ever touching this module.

§ApplyContext

ApplyContext holds all mutable apply-time state:

  • Install root — the absolute path to the game installation directory. All SqPack paths (sqpack/<expansion>/...) are resolved relative to this root by the internal path submodule.
  • Target platform — selects the win32/ps3/ps4 subfolder suffix used in SqPack file paths. Defaults to Platform::Win32 and can be overridden either at construction time with ApplyContext::with_platform or at apply time when a crate::chunk::sqpk::SqpkTargetInfo chunk is encountered.
  • Ignore flags — control whether missing files and old-data mismatches produce errors or logged warnings. SqpkTargetInfo chunks set these via the stream; callers can also pre-configure them.
  • File-handle cache — a bounded map of open file handles. Because a typical patch applies dozens of chunks to the same .dat file, re-opening that file for every chunk would be wasteful. The cache avoids this while bounding the number of simultaneously open file descriptors. See the cache section below.

§File-handle cache

Every Apply impl that writes to a SqPack file calls an internal open_cached method on ApplyContext rather than opening the file directly. The cache transparently returns an existing writable handle or opens a new one (with write=true, create=true, truncate=false).

Cached handles are wrapped in a std::io::BufWriter with a 64 KiB buffer to coalesce the many small writes the SQPK pipeline emits — block headers, zero-fill runs, decompressed DEFLATE block output — into a smaller number of write(2) syscalls. Apply functions interact with the buffered writer transparently because BufWriter implements both Write and Seek. Call ApplyContext::flush to force buffered data through to the operating system at a checkpoint of your choosing; ZiPatchReader::apply_to calls it automatically before returning.

The cache is capped at 256 entries. When it is full and a new, uncached path is requested, all cached handles are flushed and closed at once before the new one is inserted. This is a simple eviction strategy — it trades some re-open overhead at eviction boundaries for bounded file-descriptor usage. Memory cost at the cap is 256 × 64 KiB = 16 MiB.

Callers should not rely on cached handles persisting across arbitrary chunks. In particular, crate::chunk::sqpk::SqpkFile’s RemoveAll operation flushes all cached handles before bulk-deleting files to ensure no open handles survive into the deletion window (which matters on Windows). Similarly, DeleteFile evicts the cached handle for the specific path being removed.

§Ordering and idempotency

Chunks must be applied in stream order. The ZiPatch format is a sequential log, not a random-access manifest: later chunks may depend on filesystem state produced by earlier ones (e.g. an AddFile that writes blocks into a file created by an earlier MakeDirTree or AddDirectory).

Apply operations are not idempotent in general. Seeking to an offset and writing data is idempotent if the same data is written, but RemoveAll is destructive and DeleteFile can fail if the file is already gone (unless ignore_missing is set). Partial application followed by a retry requires careful state tracking at a higher level; this crate does not provide transactional semantics.

§Errors

Every Apply::apply call returns crate::Result, which is Result<(), crate::ZiPatchError>. Errors propagate from:

On error, the apply operation aborts at the failing chunk. Any changes already applied to the filesystem are not rolled back.

§Progress and cancellation

Install an ApplyObserver via ApplyContext::with_observer to be notified after each top-level chunk applies and to signal cancellation mid-stream. The observer’s on_chunk_applied method receives a ChunkEvent with the chunk index, 4-byte tag, and running byte count; its should_cancel predicate is polled between blocks inside long-running chunks so that aborting a multi- hundred-MB SqpkFile AddFile does not have to wait for the whole chunk to finish. Without an explicit observer, ApplyContext uses NoopObserver and the existing apply path pays nothing.

§Example

use std::fs::File;
use zipatch_rs::{ApplyContext, ZiPatchReader};

let patch_file = File::open("game.patch").unwrap();
let mut ctx = ApplyContext::new("/opt/ffxiv/game");

ZiPatchReader::new(patch_file)
    .unwrap()
    .apply_to(&mut ctx)
    .unwrap();

Re-exports§

pub use checkpoint::Checkpoint;
pub use checkpoint::CheckpointPolicy;
pub use checkpoint::CheckpointSink;
pub use checkpoint::InFlightAddFile;
pub use checkpoint::IndexedCheckpoint;
pub use checkpoint::NoopCheckpointSink;
pub use checkpoint::SequentialCheckpoint;

Modules§

checkpoint
Apply-time progress checkpoints — the data the library emits while a patch is being written so a consumer can persist enough state to resume a crashed/interrupted apply later.

Structs§

ApplyContext
Apply-time state: install root, target platform, flag toggles, and the internal file-handle cache used by SQPK writers.
ChunkEvent
One chunk-applied event delivered to an ApplyObserver.
NoopObserver
No-op observer used by ApplyContext when none is configured.

Enums§

ApplyMode
Selects whether ApplyContext mutates the filesystem or runs in no-op verification mode.

Traits§

Apply
Applies a parsed chunk to the filesystem via an ApplyContext.
ApplyObserver
Hook trait for observing apply-time progress and signalling cancellation.