Module: Omnizip::Formats::XzImpl::VLI

Defined in:
lib/omnizip/formats/xz_impl/vli.rb

Overview

Variable-Length Integer (VLI) codec for XZ format

XZ format uses VLIs extensively for encoding sizes and counts. Each byte has the format: 0xxxxxxx (continue) or 1xxxxxxx (last) Maximum value is 2^63 - 1 (63 bits of data)

Reference: /tmp/xz-source/src/liblzma/common/vli_decoder.c

Constant Summary collapse

MAX_VALUE =

Maximum VLI value (63 bits, as per XZ spec)

(1 << 63) - 1

Class Method Summary collapse

Class Method Details

.decode(input) ⇒ Integer

Decode a VLI from input stream

Parameters:

  • input (IO)

    Input stream

Returns:

  • (Integer)

    Decoded value

Raises:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/omnizip/formats/xz_impl/vli.rb', line 42

def self.decode(input)
  result = 0
  shift = 0
  byte_count = 0

  loop do
    byte = input.getbyte
    if byte.nil?
      raise Omnizip::IOError,
            "Unexpected end of stream in VLI"
    end
    byte_count += 1

    if shift >= 63
      raise Omnizip::FormatError,
            "VLI overflow (shift=#{shift}, max=63)"
    end

    # Add lower 7 bits to result
    result |= (byte & 0x7F) << shift

    # Check if continuation bit is set
    break if byte.nobits?(0x80)

    shift += 7
  end

  if result > MAX_VALUE
    raise Omnizip::FormatError,
          "VLI exceeds maximum (#{result} > #{MAX_VALUE})"
  end

  # XZ spec: VLIs must use minimum encoding
  # Reference: /Users/mulgogi/src/external/xz/src/liblzma/common/vli_decoder.c:77-83
  # If more than 1 byte was used, the value must be large enough to require it
  # For example, value 13 can be encoded as 0x0D (1 byte) but NOT as 0x8D 0x00 (2 bytes)
  if byte_count > 1 && result < (1 << (7 * (byte_count - 1)))
    raise FormatError,
          "VLI not minimally encoded: value #{result} uses #{byte_count} bytes, " \
          "but minimum is #{size(result)} bytes"
  end

  result
end

.encode(value) ⇒ String

Encode a value as VLI (for testing and validation)

Parameters:

  • value (Integer)

    Value to encode

Returns:

  • (String)

    Encoded bytes

Raises:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/omnizip/formats/xz_impl/vli.rb', line 92

def self.encode(value)
  if value > MAX_VALUE
    raise Omnizip::FormatError,
          "VLI value #{value} exceeds maximum #{MAX_VALUE}"
  end

  bytes = []
  loop do
    byte = value & 0x7F
    value >>= 7

    # Set continuation bit if more bytes remain
    byte |= 0x80 if value.positive?

    bytes << byte
    break if value.zero?
  end
  bytes.pack("C*")
end

.size(value) ⇒ Integer

Calculate encoded size of a VLI value

Parameters:

  • value (Integer)

    Value to measure

Returns:

  • (Integer)

    Number of bytes needed to encode



116
117
118
119
120
121
122
123
124
# File 'lib/omnizip/formats/xz_impl/vli.rb', line 116

def self.size(value)
  size = 1
  value >>= 7
  while value.positive?
    size += 1
    value >>= 7
  end
  size
end