Skip to main content

ApplyContext

Struct ApplyContext 

Source
pub struct ApplyContext { /* private fields */ }
Expand description

Apply-time state: install root, target platform, flag toggles, and the internal file-handle cache used by SQPK writers.

§Construction

Build with ApplyContext::new, then chain the with_* builder methods to override defaults:

use zipatch_rs::{ApplyContext, Platform};

let ctx = ApplyContext::new("/opt/ffxiv/game")
    .with_platform(Platform::Win32)
    .with_ignore_missing(true);

assert_eq!(ctx.game_path().to_str().unwrap(), "/opt/ffxiv/game");
assert_eq!(ctx.platform(), Platform::Win32);
assert!(ctx.ignore_missing());

§Platform mutation

The platform defaults to Platform::Win32. If the patch stream contains a crate::chunk::sqpk::SqpkTargetInfo chunk, applying it overwrites ApplyContext::platform with the platform declared in the chunk. This is the normal case: real FFXIV patches begin with a TargetInfo chunk that pins the platform, so the default is rarely used in practice.

Set the platform explicitly with ApplyContext::with_platform when you know the target in advance or are processing a synthetic patch.

§Flag mutation

ApplyContext::ignore_missing and ApplyContext::ignore_old_mismatch can also be overwritten mid-stream by ApplyOption chunks embedded in the patch file. Set initial values with the with_ignore_* builder methods.

§File-handle cache

Internally, ApplyContext maintains a bounded map of open file handles keyed by absolute path. The cache is an optimisation: a patch that writes many chunks into the same .dat file re-uses a single handle rather than opening and closing the file for every write.

The cache is capped at 256 entries. When that limit is reached and a new path is needed, all entries are evicted at once. Handles are also evicted explicitly before deleting a file (see DeleteFile) and before a RemoveAll bulk operation.

Implementations§

Source§

impl ApplyContext

Source

pub fn new(game_path: impl Into<PathBuf>) -> Self

Create a context targeting the given game install directory.

Defaults: platform is Platform::Win32, both ignore-flags are off.

Use the with_* builder methods to change these defaults before applying the first chunk.

§Example
use zipatch_rs::ApplyContext;

let ctx = ApplyContext::new("/opt/ffxiv/game");
assert_eq!(ctx.game_path().to_str().unwrap(), "/opt/ffxiv/game");
Source

pub fn game_path(&self) -> &Path

Returns the game installation directory.

All file paths produced during apply are relative to this root.

Source

pub fn platform(&self) -> Platform

Returns the current target platform.

This value may change during apply if the patch stream contains a crate::chunk::sqpk::SqpkTargetInfo chunk.

Source

pub fn ignore_missing(&self) -> bool

Returns whether missing files are silently ignored during apply.

When true, operations that target a file that does not exist log a warning instead of returning an error. This flag may be overwritten mid-stream by an ApplyOption chunk.

Source

pub fn ignore_old_mismatch(&self) -> bool

Returns whether old-data mismatches are silently ignored during apply.

When true, apply operations that detect a checksum or data mismatch against the existing on-disk content proceed without error. This flag may be overwritten mid-stream by an ApplyOption chunk.

Source

pub fn with_platform(self, platform: Platform) -> Self

Sets the target platform. Defaults to Platform::Win32.

The platform determines the directory suffix used when resolving SqPack file paths (win32, ps3, or ps4).

Note: a crate::chunk::sqpk::SqpkTargetInfo chunk encountered during apply will override this value.

Source

pub fn with_ignore_missing(self, v: bool) -> Self

Silently ignore missing files instead of returning an error during apply.

When false (the default), any apply operation that cannot find its target file returns crate::ZiPatchError::Io with kind std::io::ErrorKind::NotFound.

When true, those failures are demoted to warn!-level tracing events.

Source

pub fn with_ignore_old_mismatch(self, v: bool) -> Self

Silently ignore old-data mismatches instead of returning an error during apply.

When false (the default), an apply operation that detects that the on-disk data does not match the expected “before” state returns an error.

When true, the mismatch is logged at warn! level and the operation continues.

Source

pub fn with_observer(self, observer: impl ApplyObserver + 'static) -> Self

Install an ApplyObserver for progress reporting and cancellation.

The observer’s on_chunk_applied method is called after each top-level chunk; its should_cancel method is polled inside long-running chunks (currently the SqpkFile block-write loop) so that cancellation is observable mid-chunk on multi-hundred-MB payloads.

Returning ControlFlow::Break from on_chunk_applied, or true from should_cancel, aborts the apply loop with crate::ZiPatchError::Cancelled. Filesystem changes already applied are not rolled back.

The default observer is a no-op: parsing-only consumers and existing callers that never call with_observer pay nothing.

§'static bound

The 'static bound follows from ApplyContext storing the observer in a Box<dyn ApplyObserver> — a trait object whose lifetime parameter defaults to 'static. To pass an observer that holds a channel sender or similar handle, wrap it in Arc<Mutex<...>> (which is 'static) or implement ApplyObserver on a struct that owns the handle directly.

Source

pub fn with_checkpoint_sink(self, sink: impl CheckpointSink + 'static) -> Self

Install a CheckpointSink to receive apply-time checkpoints.

The driver hands the sink a Checkpoint at each natural recovery boundary — after every top-level chunk in the sequential apply_to loop, after every DEFLATE block inside a SqpkFile AddFile, and at the per-target / every-64-regions cadence used by crate::index::IndexApplier::execute. The sink’s CheckpointPolicy then decides whether the driver also flushes the file-handle cache or escalates to a full fsync via Self::sync_all.

Default is NoopCheckpointSink: consumers that never call this method pay nothing.

§'static bound

Mirrors Self::with_observer: the sink is boxed internally into a Box<dyn CheckpointSink> whose lifetime parameter defaults to 'static. Wrap in Arc<Mutex<...>> or implement CheckpointSink on a struct that owns the handle directly if you need to share the sink across threads.

§Panics

Panics if the sink reports CheckpointPolicy::FsyncEveryN with n == 0. A zero cadence is programmer error — either the consumer meant CheckpointPolicy::Fsync (fsync every record) or the constant was computed from a runtime value that wasn’t validated. Surfacing the check at install time keeps the failure adjacent to the bug rather than deep inside the apply loop where the cadence first matters.

Source

pub fn sync_all(&mut self) -> Result<()>

Flush every cached BufWriter, then fsync the underlying file handles.

Stronger durability guarantee than Self::flush: a successful return implies all writes have not only reached the OS but been committed to durable storage (modulo what the underlying filesystem guarantees about fsync). Used by the apply drivers when an installed CheckpointSink requests CheckpointPolicy::Fsync or hits the CheckpointPolicy::FsyncEveryN cadence.

Handles are retained in the cache after sync_all; subsequent writes reuse the existing buffered writer. Surfacing the first std::io::Error from any of the flushes or syncs aborts further processing; the rest of the cache is still attempted so that any other failing handle does not silently swallow its error.

§Errors

Returns the first std::io::Error produced by any writer’s flush or any underlying handle’s sync_all.

Source

pub fn flush(&mut self) -> Result<()>

Flush every buffered write through to the operating system.

Forces any data still sitting in BufWriter buffers (one per cached SqPack file) to be written via write(2). Open handles are retained — this is a durability checkpoint, not a cache eviction. Subsequent chunks targeting the same files reuse the existing handles.

apply_to calls this automatically before returning so successful completion of a patch implies all writes have reached the OS. Explicit calls are useful when applying chunks one at a time via Apply::apply and reading the resulting file state in between, or when implementing a custom apply driver that wants intermediate commit points.

This is not fsync. Data is handed off to the OS but may still reside in the page cache; survival across a crash requires File::sync_all on the underlying handles, which this method does not perform.

§Errors

Returns the first std::io::Error produced by any writer’s flush. Remaining writers are still attempted even if an earlier one failed.

Trait Implementations§

Source§

impl Debug for ApplyContext

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more