Module: RBStarbound::SBON

Defined in:
lib/rbstarbound/sbon.rb

Class Method Summary collapse

Class Method Details

.read_array(io) ⇒ Object



158
159
160
# File 'lib/rbstarbound/sbon.rb', line 158

def self.read_array(io)
  read_list(io)
end

.read_bool(io) ⇒ Object



119
120
121
# File 'lib/rbstarbound/sbon.rb', line 119

def self.read_bool(io)
  !read_data_type(io).zero?
end

.read_bytes(io) ⇒ Object



39
40
41
42
# File 'lib/rbstarbound/sbon.rb', line 39

def self.read_bytes(io)
  length = read_varint(io)
  io.read(length)
end

.read_data_type(io) ⇒ Object



115
116
117
# File 'lib/rbstarbound/sbon.rb', line 115

def self.read_data_type(io)
  io.readchar.ord
end

.read_double(io) ⇒ Object



131
132
133
# File 'lib/rbstarbound/sbon.rb', line 131

def self.read_double(io)
  io.read(8).unpack('G').first
end

.read_dynamic(io) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
# 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_hash(io) ⇒ Object



167
168
169
# File 'lib/rbstarbound/sbon.rb', line 167

def self.read_hash(io)
  read_map(io)
end

.read_integer(io) ⇒ Object



140
141
142
# File 'lib/rbstarbound/sbon.rb', line 140

def self.read_integer(io)
  read_varint_signed(io)
end

.read_list(io) ⇒ Object



57
58
59
60
61
62
63
# 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) ⇒ Object



72
73
74
75
76
77
78
79
# 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_nil(_) ⇒ Object



176
177
178
# File 'lib/rbstarbound/sbon.rb', line 176

def self.read_nil(_)
  nil
end

.read_str(io) ⇒ Object



149
150
151
# File 'lib/rbstarbound/sbon.rb', line 149

def self.read_str(io)
  read_string(io)
end

.read_string(io) ⇒ Object



49
50
51
# File 'lib/rbstarbound/sbon.rb', line 49

def self.read_string(io)
  read_bytes(io)
end

.read_varint(io) ⇒ Object



5
6
7
8
9
10
11
12
# 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) ⇒ Object



24
25
26
27
28
29
# 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_array(io, data) ⇒ Object



162
163
164
165
# 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) ⇒ Object



123
124
125
126
127
128
129
# 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_bytes(io, data) ⇒ Object



44
45
46
47
# File 'lib/rbstarbound/sbon.rb', line 44

def self.write_bytes(io, data)
  write_varint(io, data.length)
  io.write(data)
end

.write_double(io, value) ⇒ Object



135
136
137
138
# File 'lib/rbstarbound/sbon.rb', line 135

def self.write_double(io, value)
  io.write("\x02".b)
  io.write([value].pack('G'))
end

.write_dynamic(io, data) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
# 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_hash(io, data) ⇒ Object



171
172
173
174
# 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) ⇒ Object



144
145
146
147
# File 'lib/rbstarbound/sbon.rb', line 144

def self.write_integer(io, data)
  io.write("\x04".b)
  write_varint_signed(io, data)
end

.write_list(io, list) ⇒ Object



65
66
67
68
69
70
# 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) ⇒ Object



81
82
83
84
85
86
87
# 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_nil(io) ⇒ Object



180
181
182
# File 'lib/rbstarbound/sbon.rb', line 180

def self.write_nil(io)
  io.write("\x01".b)
end

.write_str(io, data) ⇒ Object



153
154
155
156
# File 'lib/rbstarbound/sbon.rb', line 153

def self.write_str(io, data)
  io.write("\x05".b)
  write_string(io, data)
end

.write_string(io, data) ⇒ Object



53
54
55
# File 'lib/rbstarbound/sbon.rb', line 53

def self.write_string(io, data)
  write_bytes(io, data)
end

.write_varint(io, value) ⇒ Object



14
15
16
17
18
19
20
21
22
# 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) ⇒ Object



31
32
33
34
35
36
37
# 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