#[non_exhaustive]pub enum ZiPatchError {
Show 22 variants
Io(Error),
InvalidMagic,
UnknownChunkTag([u8; 4]),
UnknownSqpkCommand(u8),
ChecksumMismatch {
tag: [u8; 4],
expected: u32,
actual: u32,
},
Decompress(Error),
InvalidField {
context: &'static str,
},
OversizedChunk(usize),
UnknownFileOperation(u8),
Utf8Error(FromUtf8Error),
BinrwError(Error),
NegativeFileOffset(i64),
TruncatedPatch,
UnsupportedPlatform(u16),
Cancelled,
IndexSourceUnavailable {
target_offset: u64,
length: u32,
},
PatchSourceTooShort {
offset: u64,
requested: usize,
},
PatchIndexOutOfRange {
patch: u32,
count: usize,
},
UnsafeTargetPath(String),
SchemaVersionMismatch {
kind: &'static str,
found: u32,
expected: u32,
},
DuplicatePatch {
name: String,
},
Crc32Mismatch {
target_offset: u64,
expected: u32,
actual: u32,
},
}Expand description
All failures returned by parsing or applying a ZiPatch stream.
Both the parsing layer (crate::chunk) and the apply layer
(crate::apply) surface errors through this single enum, so callers
need only one error type in their match arms.
§Mapping from standard errors
std::io::Errorconverts automatically via#[from]intoZiPatchError::Io.std::string::FromUtf8Errorconverts automatically intoZiPatchError::Utf8Error.binrw::Errorconverts automatically intoZiPatchError::BinrwError.
§Example
use zipatch_rs::ZiPatchError;
fn describe(e: &ZiPatchError) -> &'static str {
match e {
ZiPatchError::Io(_) => "I/O error",
ZiPatchError::InvalidMagic => "not a ZiPatch file",
ZiPatchError::UnknownChunkTag(_) => "unrecognised chunk",
ZiPatchError::ChecksumMismatch {..}=> "corrupt chunk",
ZiPatchError::TruncatedPatch => "download incomplete",
_ => "other error",
}
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Io(Error)
Underlying I/O failure from the patch source or target filesystem.
Raised by the parsing layer when reading from the patch stream fails (e.g. a network read error), and by the apply layer when any filesystem operation fails (open, seek, write, delete, create-dir).
The wrapped std::io::Error carries the OS-level error code and kind.
Use std::io::Error::kind to distinguish NotFound, PermissionDenied,
and similar conditions.
InvalidMagic
The 12-byte ZiPatch magic header was missing or did not match.
Raised by ZiPatchReader::new and
ZiPatchReader::from_path when
the first 12 bytes of the source do not equal the expected magic
sequence \x91ZIPATCH\r\n\x1a\n. Typically indicates the caller opened
the wrong file, or the file is corrupted at the very start.
UnknownChunkTag([u8; 4])
A 4-byte chunk tag was not recognised by the parser.
Raised by the chunk dispatcher in crate::chunk when a tag does not
match any of FHDR, APLY, APFS, ADIR, DELD, SQPK, or
EOF_. The raw tag bytes are preserved so callers can log them for
diagnostic purposes.
This can occur with genuinely new chunk types introduced by Square Enix in future patches. Upgrading the library or filing an issue is the appropriate response.
UnknownSqpkCommand(u8)
A SQPK sub-command byte was not recognised by the parser.
Raised by the SQPK dispatcher in crate::chunk when the single-byte
command code inside an SQPK chunk does not match any of the known
values (A, D, E, F, H, I, T, X). The raw byte is
preserved for diagnostics.
ChecksumMismatch
A chunk’s recorded CRC32 did not match the computed CRC32.
Raised by the chunk framing code in crate::chunk when CRC32
verification is enabled (the default) and the stored checksum in the
patch stream does not match the checksum computed over tag ++ body.
This indicates a corrupt or partially-written patch file. Disable
verification with
ZiPatchReader::skip_checksum_verification
if the source has already been verified out-of-band.
The tag, expected, and actual fields provide enough information
to log a precise diagnostic message.
Fields
Decompress(Error)
DEFLATE decompression of a SqpkFile block failed.
Raised by the SqpkFile apply logic when flate2 cannot decompress
a compressed block payload inside an AddFile operation. The wrapped
std::io::Error is the decompressor’s error, not a filesystem error;
it is stored as a #[source] rather than #[from] to keep it distinct
from ZiPatchError::Io.
InvalidField
A field value failed a parser invariant (e.g. negative size).
Raised by chunk-specific parsers in crate::chunk when a field
value is syntactically valid (i.e. could be parsed) but violates a
semantic constraint required by the format — for example, a length
field that is negative, or a size that overflows the expected range.
The context string names the specific field that failed its check,
giving enough information to locate the offending position in the
binary format documentation.
OversizedChunk(usize)
A chunk declared a size larger than the parser’s maximum (512 MiB).
Raised by the chunk framing code in crate::chunk when the
body_len field of a chunk frame exceeds 512 MiB. This guard prevents
allocating an arbitrarily large buffer from a malformed or malicious
patch stream. The preserved size value can be logged for diagnostics.
UnknownFileOperation(u8)
A SqpkFile operation byte was not recognised.
Raised by the SqpkFile parser when the single-byte operation field
does not match any of A (AddFile), R (RemoveAll), D (DeleteFile),
or M (MakeDirTree). The raw byte is preserved for diagnostics.
Utf8Error(FromUtf8Error)
A UTF-8 decode failed when reading a path or name field.
Raised by the parsing layer when a length-prefixed byte string (e.g. a
directory name in an ADIR chunk or a file path in a SqpkFile chunk)
is not valid UTF-8. FFXIV patch paths are documented as ASCII, so this
error indicates either a corrupt patch file or an undocumented encoding
extension.
BinrwError(Error)
A binrw parser produced an error; wraps the underlying cause.
Several chunk types (notably those using #[derive(BinRead)]) delegate
their parsing to binrw. When binrw encounters an unexpected byte
pattern or short read, it returns a binrw::Error which is wrapped
here via #[from].
The inner error message usually identifies the field name and byte offset where parsing failed.
NegativeFileOffset(i64)
A SqpkFile carried a negative file_offset that cannot be applied.
Raised by the AddFile arm of the SqpkFile apply logic when
cmd.file_offset is negative and therefore cannot be converted to a
u64 seek position. The wire format stores this field as i64;
a non-negative value is the invariant required for correct application.
The preserved i64 value can be logged to report the exact field content.
TruncatedPatch
Stream ended without an EOF_ chunk; download or copy was truncated.
Raised by the chunk framing code when attempting to read the 4-byte
body_len field of the next chunk returns an unexpected EOF. This
indicates the patch stream ended before the mandatory EOF_ terminator
chunk was encountered — the patch file was likely incompletely
downloaded or written to disk.
Use ZiPatchReader::is_complete
after iteration to distinguish this case from a clean end of stream.
UnsupportedPlatform(u16)
SqPack path resolution refused to fall back to a default platform layout.
Raised by the apply layer’s internal dat_path and index_path
resolvers when crate::apply::ApplyContext::platform
is crate::Platform::Unknown: the parser tolerates unrecognised
platform_id values from SqpkTargetInfo
so that future platforms do not hard-fail parsing, but the apply layer
refuses to resolve a .dat/.index path against a guessed-at platform —
silently misrouting writes to e.g. the win32 layout would corrupt the
on-disk install. The wrapped u16 is the raw platform_id carried by
the offending TargetInfo chunk, so callers can surface it to users.
Callers who legitimately know which platform layout to use can override
the context after the TargetInfo chunk has been applied (which
requires manual chunk iteration rather than
ZiPatchReader::apply_to) by setting
crate::apply::ApplyContext::platform back to a concrete variant.
Cancelled
Apply was cancelled by an ApplyObserver.
Raised by ZiPatchReader::apply_to
when an observer returns
std::ops::ControlFlow::Break from
ApplyObserver::on_chunk_applied,
or when
ApplyObserver::should_cancel
returns true during a long-running chunk (currently checked between
blocks of an SqpkFile AddFile
operation).
Cancellation is best-effort: filesystem changes already applied by previous chunks — or by previous blocks within the cancelled chunk — are not rolled back. The format provides no transactional semantics, so callers expecting clean cancellation must perform their own recovery at a higher level (e.g. by re-running the patch from scratch against a clean install snapshot).
An indexed-apply plan referenced a region whose source bytes are not reachable from the current applier.
Raised by crate::index::IndexApplier when it encounters a
crate::index::PartSource::Unavailable region. The builder does not
emit this variant from any in-tree chunk parser, so reaching it
typically means the plan was hand-constructed (or deserialized) with an
explicit crate::index::PartSource::Unavailable region whose source
bytes are not in the crate::index::PatchSource the applier was
constructed with.
PatchSourceTooShort
A crate::index::PatchSource::read call could not fill the requested
buffer.
Raised by crate::index::IndexApplier (via the built-in
crate::index::FilePatchSource /
[crate::index::MemoryPatchSource] implementations) when the source
has fewer than requested bytes available at offset — i.e. the
underlying file or buffer is shorter than the plan expected, or the
caller passed an offset past the end. Indicates either a truncated
patch source or a plan that does not match the source it is being
applied against.
Fields
PatchIndexOutOfRange
A crate::index::PatchSource::read call asked for a patch index
outside the source’s configured chain.
Raised by crate::index::FilePatchSource /
[crate::index::MemoryPatchSource] when the applier passes a
patch: u32 value >= count. Indicates either a stale plan referring
to a patch the source no longer carries, or an off-by-one in a
hand-built chain source.
Fields
UnsafeTargetPath(String)
An indexed-plan target or filesystem-op carried a path that escapes the install root.
Raised by crate::index::PlanBuilder when a chunk carries a relative
path that contains a .. component, starts with / (absolute Unix
path), or starts with a Windows drive-letter prefix (e.g. C:\). The
indexed builder is a natural choke point for this check; the sequential
apply path does not currently reject these paths (writes would land
outside the install root if a malicious patch supplied one), but the
indexed builder refuses to construct the plan rather than building one
that would point at the wrong filesystem location. SqPack-encoded
targets (crate::index::TargetPath::SqpackDat /
crate::index::TargetPath::SqpackIndex) are structurally constrained
by their numeric (main_id, sub_id, file_id) triple and are not subject
to this check.
SchemaVersionMismatch
A serialized type carrying a schema_version field was decoded with a
version this build cannot represent.
Raised by crate::index::Plan::check_schema_version and by the
resume side of the apply-checkpoint surface when a persisted record’s
schema_version does not equal the constant this build pins. Older
readers refuse to silently drop fields they cannot understand rather
than risk an apply against a partial decode.
The kind field is a &'static str naming which type’s schema the
mismatch refers to ("plan" for crate::index::Plan, future kinds
for the checkpoint structs). found is the persisted version,
expected the constant this build supports.
Fields
DuplicatePatch
Two patches in the same chain shared a name.
Raised by crate::index::PlanBuilder::add_patch (and the freestanding
crate::index::build_plan_chain) when a patch with the same name
has already been added to this builder. The chain protocol is
order-sensitive — re-adding the same patch almost always indicates a
caller accidentally fed the same source into the chain twice, which
would produce a Plan whose patches vector carries duplicate entries
and whose region timelines reapply the same bytes. The builder refuses
to construct the plan rather than silently letting this slip through.
The duplicate name is preserved so callers can log it.
Crc32Mismatch
A region’s post-write CRC32 did not match the expected value.
Reserved for content-CRC verification flows that operate on plans
populated by crate::index::Plan::compute_crc32. The default builder
only emits crate::index::PartExpected::SizeOnly / Zeros /
EmptyBlock, so this variant is only reached once a plan has had
CRC32 expectations populated and a downstream check compares observed
bytes against them.
Trait Implementations§
Source§impl Debug for ZiPatchError
impl Debug for ZiPatchError
Source§impl Display for ZiPatchError
impl Display for ZiPatchError
Source§impl Error for ZiPatchError
impl Error for ZiPatchError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<Error> for ZiPatchError
impl From<Error> for ZiPatchError
Source§impl From<Error> for ZiPatchError
impl From<Error> for ZiPatchError
Source§impl From<FromUtf8Error> for ZiPatchError
impl From<FromUtf8Error> for ZiPatchError
Source§fn from(source: FromUtf8Error) -> Self
fn from(source: FromUtf8Error) -> Self
Auto Trait Implementations§
impl Freeze for ZiPatchError
impl !RefUnwindSafe for ZiPatchError
impl Send for ZiPatchError
impl Sync for ZiPatchError
impl Unpin for ZiPatchError
impl UnsafeUnpin for ZiPatchError
impl !UnwindSafe for ZiPatchError
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> CustomError for T
impl<T> CustomError for 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