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
impl ApplyContext
Sourcepub fn new(game_path: impl Into<PathBuf>) -> Self
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");Sourcepub fn game_path(&self) -> &Path
pub fn game_path(&self) -> &Path
Returns the game installation directory.
All file paths produced during apply are relative to this root.
Sourcepub fn platform(&self) -> Platform
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.
Sourcepub fn ignore_missing(&self) -> bool
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.
Sourcepub fn ignore_old_mismatch(&self) -> bool
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.
Sourcepub fn with_platform(self, platform: Platform) -> Self
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.
Sourcepub fn with_ignore_missing(self, v: bool) -> Self
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.
Sourcepub fn with_ignore_old_mismatch(self, v: bool) -> Self
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.
Sourcepub fn with_observer(self, observer: impl ApplyObserver + 'static) -> Self
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.
Sourcepub fn with_checkpoint_sink(self, sink: impl CheckpointSink + 'static) -> Self
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.
Sourcepub fn sync_all(&mut self) -> Result<()>
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.
Sourcepub fn flush(&mut self) -> Result<()>
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§
Auto Trait Implementations§
impl Freeze for ApplyContext
impl !RefUnwindSafe for ApplyContext
impl !Send for ApplyContext
impl !Sync for ApplyContext
impl Unpin for ApplyContext
impl UnsafeUnpin for ApplyContext
impl !UnwindSafe for ApplyContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more