Class: Optimize::Codec::Header

Inherits:
Struct
  • Object
show all
Defined in:
lib/optimize/codec/header.rb

Overview

IBF header — the fixed-size 40-byte record at offset 0 of every YARB binary.

Layout (from research/cruby/ibf-format.md §1):

Offset  Size  Field
     0     4  magic                    — b"YARB"
     4     4  major_version            — uint32_t
     8     4  minor_version            — uint32_t
    12     4  size                     — uint32_t, total binary size (excl. extra)
    16     4  extra_size               — uint32_t
    20     4  iseq_list_size           — uint32_t, number of iseq records
    24     4  global_object_list_size  — uint32_t
    28     4  iseq_list_offset         — uint32_t, absolute byte offset
    32     4  global_object_list_offset — uint32_t, absolute byte offset
    36     1  endian                   — uint8_t ('l' or 'b')
    37     1  wordsize                 — uint8_t (sizeof VALUE, typically 8)
    38     2  (padding)                — implicit C struct padding, always zero
Total: 40 bytes

Constant Summary collapse

BYTE_SIZE =
40
IBF_EXPECTED_MAJOR_VERSION =

The IBF version this codec was written against. CRuby defines IBF_MAJOR_VERSION / IBF_MINOR_VERSION as ruby_api_version / [1]; for Ruby 4.0.x that’s (4, 0). The CRuby loader rejects any binary whose stamps don’t match exactly — mirror that here so a cross-version blob fails at decode instead of producing nonsense. Defined outside the Struct.new block because constants declared inside it land on the enclosing module, not on the struct itself.

4
IBF_EXPECTED_MINOR_VERSION =
0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#endianObject

Returns the value of attribute endian

Returns:

  • (Object)

    the current value of endian



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def endian
  @endian
end

#extra_sizeObject

Returns the value of attribute extra_size

Returns:

  • (Object)

    the current value of extra_size



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def extra_size
  @extra_size
end

#global_object_list_offsetObject

Returns the value of attribute global_object_list_offset

Returns:

  • (Object)

    the current value of global_object_list_offset



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def global_object_list_offset
  @global_object_list_offset
end

#global_object_list_sizeObject

Returns the value of attribute global_object_list_size

Returns:

  • (Object)

    the current value of global_object_list_size



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def global_object_list_size
  @global_object_list_size
end

#iseq_list_offsetObject

Returns the value of attribute iseq_list_offset

Returns:

  • (Object)

    the current value of iseq_list_offset



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def iseq_list_offset
  @iseq_list_offset
end

#iseq_list_sizeObject

Returns the value of attribute iseq_list_size

Returns:

  • (Object)

    the current value of iseq_list_size



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def iseq_list_size
  @iseq_list_size
end

#magicObject

Returns the value of attribute magic

Returns:

  • (Object)

    the current value of magic



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def magic
  @magic
end

#major_versionObject

Returns the value of attribute major_version

Returns:

  • (Object)

    the current value of major_version



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def major_version
  @major_version
end

#minor_versionObject

Returns the value of attribute minor_version

Returns:

  • (Object)

    the current value of minor_version



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def minor_version
  @minor_version
end

#paddingObject

Returns the value of attribute padding

Returns:

  • (Object)

    the current value of padding



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def padding
  @padding
end

#sizeObject

Returns the value of attribute size

Returns:

  • (Object)

    the current value of size



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def size
  @size
end

#wordsizeObject

Returns the value of attribute wordsize

Returns:

  • (Object)

    the current value of wordsize



26
27
28
# File 'lib/optimize/codec/header.rb', line 26

def wordsize
  @wordsize
end

Class Method Details

.decode(reader) ⇒ Object

Decode a Header from the current position of reader. Raises Optimize::Codec::MalformedBinary if the magic bytes are wrong, or Optimize::Codec::UnmatchedIBFVersion if the version stamp doesn’t match the version this codec targets.



39
40
41
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
# File 'lib/optimize/codec/header.rb', line 39

def self.decode(reader)
  magic                    = reader.read_bytes(4)
  unless magic == "YARB".b
    raise Codec::MalformedBinary, "invalid magic bytes: expected 'YARB', got #{magic.inspect}"
  end
  major_version            = reader.read_u32
  minor_version            = reader.read_u32
  if major_version != Header::IBF_EXPECTED_MAJOR_VERSION ||
     minor_version != Header::IBF_EXPECTED_MINOR_VERSION
    raise Codec::UnmatchedIBFVersion.new(
      expected_major: Header::IBF_EXPECTED_MAJOR_VERSION,
      expected_minor: Header::IBF_EXPECTED_MINOR_VERSION,
      actual_major:   major_version,
      actual_minor:   minor_version,
    )
  end
  size                     = reader.read_u32
  extra_size               = reader.read_u32
  iseq_list_size           = reader.read_u32
  global_object_list_size  = reader.read_u32
  iseq_list_offset         = reader.read_u32
  global_object_list_offset = reader.read_u32
  endian                   = reader.read_u8
  wordsize                 = reader.read_u8
  padding                  = reader.read_bytes(2)

  new(
    magic: magic,
    major_version: major_version,
    minor_version: minor_version,
    size: size,
    extra_size: extra_size,
    iseq_list_size: iseq_list_size,
    global_object_list_size: global_object_list_size,
    iseq_list_offset: iseq_list_offset,
    global_object_list_offset: global_object_list_offset,
    endian: endian,
    wordsize: wordsize,
    padding: padding,
  )
end

Instance Method Details

#encode(writer) ⇒ Object

Encode this header into writer, producing the original 40 bytes.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/optimize/codec/header.rb', line 89

def encode(writer)
  writer.write_bytes(magic)
  writer.write_u32(major_version)
  writer.write_u32(minor_version)
  writer.write_u32(size)
  writer.write_u32(extra_size)
  writer.write_u32(iseq_list_size)
  writer.write_u32(global_object_list_size)
  writer.write_u32(iseq_list_offset)
  writer.write_u32(global_object_list_offset)
  writer.write_u8(endian)
  writer.write_u8(wordsize)
  writer.write_bytes(padding)
end

#platformObject

Returns a human-readable platform descriptor derived from endian and wordsize. The YARB header does not store a platform string; this is synthesized.



83
84
85
86
# File 'lib/optimize/codec/header.rb', line 83

def platform
  endian_name = endian == 108 ? "little-endian" : "big-endian"  # 108 = 'l'.ord
  "#{endian_name}/#{wordsize * 8}-bit"
end