module RBStarbound::SBON

Public Class Methods

read_bytes(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 39
def self.read_bytes(io)
  length = read_varint(io)
  io.read(length)
end
read_dynamic(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 89
def self.read_dynamic(io)
  case read_data_type(io)
  when 1 then read_nil(io)
  when 2 then read_double(io) # big-endian
  when 3 then read_bool(io)
  when 4 then read_integer(io) # VLQ; signed
  when 5 then read_str(io)
  when 6 then read_array(io)
  when 7 then read_hash(io)
  else raise RBStarbound::ValueError, 'Unknown dynamic type'
  end
end
read_list(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 57
def self.read_list(io)
  list = []
  read_varint(io).times do
    list << read_dynamic(io)
  end
  list
end
read_map(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 72
def self.read_map(io)
  map = {}
  read_varint(io).times do
    key = read_string(io)
    map[key] = read_dynamic(io)
  end
  map
end
read_string(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 49
def self.read_string(io)
  read_bytes(io)
end
read_varint(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 5
def self.read_varint(io)
  value = 0
  loop do
    byte = io.readchar.ord
    return value << 7 | byte if (byte & 0b10_00_00_00).zero?
    value = value << 7 | (byte & 0b01_11_11_11)
  end
end
read_varint_signed(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 24
def self.read_varint_signed(io)
  value = read_varint(io)
  # Least significant bit represents the sign.
  return -(value >> 1) - 1 unless (value & 1).zero?
  value >> 1
end
write_bytes(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 44
def self.write_bytes(io, data)
  write_varint(io, data.length)
  io.write(data)
end
write_dynamic(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 102
def self.write_dynamic(io, data)
  case data
  when nil                   then write_nil(io)
  when Float                 then write_double(io, data)
  when TrueClass, FalseClass then write_bool(io, data)
  when Integer               then write_integer(io, data)
  when String                then write_str(io, data)
  when Array                 then write_array(io, data)
  when Hash                  then write_hash(io, data)
  else raise ValueError, 'Cannot write value'
  end
end
write_list(io, list) click to toggle source
# File lib/rbstarbound/sbon.rb, line 65
def self.write_list(io, list)
  write_varint(io, list.length)
  list.each do |item|
    write_dynamic(io, item)
  end
end
write_map(io, map) click to toggle source
# File lib/rbstarbound/sbon.rb, line 81
def self.write_map(io, map)
  write_varint(io, map.length)
  map.each_pair do |key, val|
    write_string(io, key)
    write_dynamic(io, val)
  end
end
write_string(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 53
def self.write_string(io, data)
  write_bytes(io, data)
end
write_varint(io, value) click to toggle source
# File lib/rbstarbound/sbon.rb, line 14
def self.write_varint(io, value)
  buf = (value & 0b01_11_11_11).chr
  value >>= 7
  until value.zero?
    buf = (value & 0b01_11_11_11 | 0b10_00_00_00).chr + buf
    value >>= 7
  end
  io.write(buf)
end
write_varint_signed(io, value) click to toggle source
# File lib/rbstarbound/sbon.rb, line 31
def self.write_varint_signed(io, value)
  if value < 0
    write_varint(io, (-(value + 1) << 1 | 1))
  else
    write_varint(io, value << 1)
  end
end

Private Class Methods

read_array(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 158
def self.read_array(io)
  read_list(io)
end
read_bool(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 119
def self.read_bool(io)
  !read_data_type(io).zero?
end
read_data_type(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 115
def self.read_data_type(io)
  io.readchar.ord
end
read_double(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 131
def self.read_double(io)
  io.read(8).unpack('G').first
end
read_hash(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 167
def self.read_hash(io)
  read_map(io)
end
read_integer(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 140
def self.read_integer(io)
  read_varint_signed(io)
end
read_nil(_) click to toggle source
# File lib/rbstarbound/sbon.rb, line 176
def self.read_nil(_)
  nil
end
read_str(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 149
def self.read_str(io)
  read_string(io)
end
write_array(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 162
def self.write_array(io, data)
  io.write("\x06".b)
  write_list(io, data)
end
write_bool(io, value) click to toggle source
# File lib/rbstarbound/sbon.rb, line 123
def self.write_bool(io, value)
  if value.is_a? TrueClass
    io.write("\x03\x01".b)
  else
    io.write("\x03\x00".b)
  end
end
write_double(io, value) click to toggle source
# File lib/rbstarbound/sbon.rb, line 135
def self.write_double(io, value)
  io.write("\x02".b)
  io.write([value].pack('G'))
end
write_hash(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 171
def self.write_hash(io, data)
  io.write("\x07".b)
  write_map(io, data)
end
write_integer(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 144
def self.write_integer(io, data)
  io.write("\x04".b)
  write_varint_signed(io, data)
end
write_nil(io) click to toggle source
# File lib/rbstarbound/sbon.rb, line 180
def self.write_nil(io)
  io.write("\x01".b)
end
write_str(io, data) click to toggle source
# File lib/rbstarbound/sbon.rb, line 153
def self.write_str(io, data)
  io.write("\x05".b)
  write_string(io, data)
end