Class: Omnizip::Formats::XzImpl::IndexEncoder

Inherits:
Object
  • Object
show all
Includes:
Omnizip::Formats::XzConst
Defined in:
lib/omnizip/formats/xz_impl/index_encoder.rb

Overview

XZ Index encoder Stores positions and sizes of all blocks in the stream

Constant Summary

Constants included from Omnizip::Formats::XzConst

Omnizip::Formats::XzConst::BACKWARD_SIZE_MAX, Omnizip::Formats::XzConst::BACKWARD_SIZE_MIN, Omnizip::Formats::XzConst::BLOCK_HEADER_SIZE_MAX, Omnizip::Formats::XzConst::BLOCK_HEADER_SIZE_MIN, Omnizip::Formats::XzConst::CHECK_CRC32, Omnizip::Formats::XzConst::CHECK_CRC64, Omnizip::Formats::XzConst::CHECK_NONE, Omnizip::Formats::XzConst::CHECK_SHA256, Omnizip::Formats::XzConst::FILTERS_MAX, Omnizip::Formats::XzConst::FILTER_LZMA2, Omnizip::Formats::XzConst::FOOTER_MAGIC, Omnizip::Formats::XzConst::INDEX_INDICATOR, Omnizip::Formats::XzConst::MAGIC, Omnizip::Formats::XzConst::STREAM_FLAGS_SIZE, Omnizip::Formats::XzConst::STREAM_FOOTER_SIZE, Omnizip::Formats::XzConst::STREAM_HEADER_SIZE, Omnizip::Formats::XzConst::VLI_BYTES_MAX, Omnizip::Formats::XzConst::VLI_UNKNOWN

Instance Method Summary collapse

Constructor Details

#initializeIndexEncoder

Returns a new instance of IndexEncoder.



14
15
16
# File 'lib/omnizip/formats/xz_impl/index_encoder.rb', line 14

def initialize
  @records = []
end

Instance Method Details

#add_record(unpadded_size, uncompressed_size) ⇒ Object

Add a block record to the index

Parameters:

  • unpadded_size (Integer)

    Block size without padding

  • uncompressed_size (Integer)

    Uncompressed size of the block



21
22
23
24
25
26
# File 'lib/omnizip/formats/xz_impl/index_encoder.rb', line 21

def add_record(unpadded_size, uncompressed_size)
  @records << {
    unpadded: unpadded_size,
    uncompressed: uncompressed_size,
  }
end

#encodeObject

Encode the complete index Returns the encoded index as a binary string



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/omnizip/formats/xz_impl/index_encoder.rb', line 30

def encode
  output = StringIO.new
  output.set_encoding(Encoding::BINARY)

  # Index Indicator (0x00)
  output.write("\x00")

  # Number of Records
  output.write(encode_vli(@records.size))

  # Encode each record
  @records.each do |record|
    # Unpadded Size
    output.write(encode_vli(record[:unpadded]))

    # Uncompressed Size
    output.write(encode_vli(record[:uncompressed]))
  end

  # Add padding to make index multiple of 4 bytes (including CRC32)
  # CRITICAL: Capture index_data before writing padding (StringIO#string returns a reference!)
  index_data = output.string.dup # Make a copy to avoid reference
  padding = calculate_padding(index_data.bytesize) # Pad to multiple of 4
  output.write("\x00" * padding) if padding.positive?

  # Calculate and write CRC32
  crc = Zlib.crc32(index_data + ("\x00" * padding))
  output.write([crc].pack("V"))

  output.string
end

#sizeObject

Get the size of the encoded index (for backward size)



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/omnizip/formats/xz_impl/index_encoder.rb', line 63

def size
  # Calculate without actually encoding
  size = 1 # Index Indicator
  size += vli_size(@records.size)

  @records.each do |record|
    size += vli_size(record[:unpadded])
    size += vli_size(record[:uncompressed])
  end

  # Add CRC32
  size += 4

  # Round up to multiple of 4
  ((size + 3) / 4) * 4
end