Skip to main content

SqpkCompressedBlock

Struct SqpkCompressedBlock 

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

One block of a SqpkFile AddFile payload, which may be DEFLATE-compressed or stored raw.

SqpkFile payloads are split into a sequence of these blocks. Each block begins with a 16-byte little-endian header that describes the compressed and decompressed sizes, followed by the data bytes padded to a 128-byte boundary.

§Compression sentinel

The compressed_size field in the wire header uses the value 0x7d00 (decimal 32000) as a sentinel meaning “this block is not compressed”. Any other value means the data bytes are a raw DEFLATE stream (no zlib wrapper, no gzip header — just RFC 1951 raw deflate).

§Wire format of one block (all little-endian)

┌─────────────────────────────────────────────────────────────────────┐
│ header_size     : i32 LE   always 16 in practice                   │  bytes 0–3
│ <pad>           : u32 LE   always zero                              │  bytes 4–7
│ compressed_size : i32 LE   byte count of DEFLATE data               │  bytes 8–11
│                             OR 0x7d00 (32000) if uncompressed       │
│ decompressed_size : i32 LE  byte count of decompressed output       │  bytes 12–15
│ data            : [u8]     compressed or raw bytes                  │  bytes 16–…
│ <alignment>     : [u8]     zero-padding to 128-byte boundary        │
└─────────────────────────────────────────────────────────────────────┘

§128-byte alignment formula

The total byte count to read for a block’s data + alignment is:

block_len = (data_len + 143) & !127

where data_len is compressed_size if compressed, or decompressed_size if uncompressed. The constant 143 is 128 - 1 + 16 (subtract the 16-byte header that is not included in data_len, then round up to the next 128-byte boundary). The number of data bytes actually read is block_len - header_size; the alignment padding is consumed but discarded.

§pub(crate) visibility

SqpkCompressedBlock is pub so that it appears in rustdoc and can be named in SqpkFile::blocks, but it can only be constructed via new (for tests) or by parsing a SqpkFile.

See SqpkFile.cs / ZiPatchConfig.cs in the XIVLauncher reference implementation.

Implementations§

Source§

impl SqpkCompressedBlock

Source

pub fn new(is_compressed: bool, decompressed_size: usize, data: Vec<u8>) -> Self

Construct a block directly from its component parts.

This constructor exists primarily for unit tests. Production code creates blocks by parsing a SqpkFile from a patch byte stream.

  • is_compressed: true if data is a raw DEFLATE stream.
  • decompressed_size: the expected number of bytes after decompression; used to pre-allocate the output buffer in decompress.
  • data: raw compressed bytes or exact uncompressed bytes, depending on is_compressed.
Source

pub fn decompress_into(&self, w: &mut impl Write) -> Result<()>

Stream the block’s decompressed bytes into w.

For uncompressed blocks, w.write_all(&self.data) is called directly. For compressed blocks, the data is piped through DeflateDecoder (raw DEFLATE, RFC 1951 — no zlib or gzip wrapper) before being written.

This is the primary write path used by the apply layer: each block in a SqpkFile AddFile operation is streamed into the target file handle in sequence.

§Errors
Source

pub fn decompress_into_with( &self, decompressor: &mut Decompress, w: &mut impl Write, ) -> Result<()>

Stream the block’s decompressed bytes into w, reusing a caller-owned Decompress state across blocks.

Equivalent to decompress_into in behaviour and error semantics, but avoids the per-call ~100 KiB zlib-state allocation that DeflateDecoder::new would otherwise pay. The apply layer threads a single Decompress through every block in a multi-block SqpkFile::AddFile chunk; uncompressed blocks short-circuit to write_all and leave the decompressor untouched.

decompressor is reset via Decompress::reset(false) at the start of every compressed block, so callers may pass an already-used state without manually resetting it.

§Errors
Source

pub fn is_compressed(&self) -> bool

Returns true if the block stores a raw DEFLATE stream.

false means the block carries already-decompressed bytes (the compressed_size == 0x7d00 sentinel).

Source

pub fn decompressed_size(&self) -> usize

Returns the block’s expected decompressed length in bytes.

Source

pub fn data_len(&self) -> usize

Returns the byte length of the block’s stored data slab.

For compressed blocks this is the length of the DEFLATE payload as the parser stored it (which may include trailing 128-byte alignment padding that the decoder ignores past the end-of-stream marker). For uncompressed blocks it equals decompressed_size.

Source

pub fn decompress(&self) -> Result<Cow<'_, [u8]>>

Return the block’s decompressed bytes as a Cow.

Uncompressed blocks return Cow::Borrowed(&self.data) — a zero-copy borrow into the block’s existing buffer. Compressed blocks decompress into a newly allocated Vec and return Cow::Owned.

Use decompress_into instead when writing to a file handle, to avoid the intermediate allocation.

§Errors

Trait Implementations§

Source§

impl Clone for SqpkCompressedBlock

Source§

fn clone(&self) -> SqpkCompressedBlock

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SqpkCompressedBlock

Source§

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

Formats the value using the given formatter. Read more
Source§

impl PartialEq for SqpkCompressedBlock

Source§

fn eq(&self, other: &SqpkCompressedBlock) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for SqpkCompressedBlock

Source§

impl StructuralPartialEq for SqpkCompressedBlock

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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