Class: Optimize::Codec::BinaryWriter

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

Instance Method Summary collapse

Constructor Details

#initializeBinaryWriter

Returns a new instance of BinaryWriter.



6
7
8
# File 'lib/optimize/codec/binary_writer.rb', line 6

def initialize
  @buffer = String.new(encoding: Encoding::ASCII_8BIT)
end

Instance Method Details

#align_to(alignment) ⇒ Object

Pad with zero bytes until pos is aligned to alignment bytes.



23
24
25
26
# File 'lib/optimize/codec/binary_writer.rb', line 23

def align_to(alignment)
  remainder = @buffer.bytesize % alignment
  write_bytes("\x00" * (alignment - remainder)) if remainder != 0
end

#bufferObject



10
# File 'lib/optimize/codec/binary_writer.rb', line 10

def buffer = @buffer

#posObject



20
# File 'lib/optimize/codec/binary_writer.rb', line 20

def pos = @buffer.bytesize

#write_bytes(bytes) ⇒ Object



17
# File 'lib/optimize/codec/binary_writer.rb', line 17

def write_bytes(bytes) = @buffer << bytes.b

#write_cstr(s) ⇒ Object



18
# File 'lib/optimize/codec/binary_writer.rb', line 18

def write_cstr(s)      = @buffer << s.b << "\x00".b

#write_small_value(value) ⇒ Object

Encode a small_value (variable-length unsigned integer). See research/cruby/ibf-format.md §6 for the encoding.

Layout: the first byte carries a unary marker in its trailing bits:

XXXXXXX1  → 1 byte,  value ≤ 0x7f
XXXXXX10  → 2 bytes, value ≤ 0x3fff
XXXXX100  → 3 bytes, value ≤ 0x1fffff
XXXX1000  → 4 bytes, value ≤ 0x0fffffff
00000000  → 9 bytes, full uint64

The value bits after the marker are stored big-endian across subsequent bytes.

Raises:

  • (ArgumentError)


38
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
# File 'lib/optimize/codec/binary_writer.rb', line 38

def write_small_value(value)
  raise ArgumentError, "small_value must be non-negative, got #{value}" if value.negative?
  if value <= 0x7f
    @buffer << [((value << 1) | 1)].pack("C")
  elsif value <= 0x3fff
    b1 = value & 0xff
    b0 = ((value >> 8) << 2) | 2
    @buffer << [b0, b1].pack("CC")
  elsif value <= 0x1f_ffff
    b2 = value & 0xff
    b1 = (value >> 8) & 0xff
    b0 = ((value >> 16) << 3) | 4
    @buffer << [b0, b1, b2].pack("CCC")
  elsif value <= 0x0fff_ffff
    b3 = value & 0xff
    b2 = (value >> 8) & 0xff
    b1 = (value >> 16) & 0xff
    b0 = ((value >> 24) << 4) | 8
    @buffer << [b0, b1, b2, b3].pack("CCCC")
  else
    # 9-byte form for large values: full uint64 big-endian
    # (ibf_dump_small_value uses the same big-endian shift algorithm as the
    # general case: "value = (value << 8) | byte[i]" for i in [1..8)).
    @buffer << "\x00".b << [value].pack("Q>")
  end
end

#write_u16(v) ⇒ Object



13
# File 'lib/optimize/codec/binary_writer.rb', line 13

def write_u16(v) = write_int(v, "v")

#write_u32(v) ⇒ Object



14
# File 'lib/optimize/codec/binary_writer.rb', line 14

def write_u32(v) = write_int(v, "V")

#write_u64(v) ⇒ Object



15
# File 'lib/optimize/codec/binary_writer.rb', line 15

def write_u64(v) = write_int(v, "Q<")

#write_u8(v) ⇒ Object



12
# File 'lib/optimize/codec/binary_writer.rb', line 12

def write_u8(v)  = write_int(v, "C")