msgpack-inspect 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +3 -4
- data/Dockerfile +1 -0
- data/README.md +37 -1
- data/Rakefile +126 -14
- data/build_config.rb +94 -0
- data/docker-compose.yml +23 -0
- data/exe/msgpack-inspect +1 -0
- data/lib/msgpack/inspect.rb +4 -3
- data/lib/msgpack/inspect/command.rb +7 -1
- data/lib/msgpack/inspect/example.json +48 -0
- data/lib/msgpack/inspect/example.yml +34 -0
- data/lib/msgpack/inspect/inspector.rb +53 -287
- data/lib/msgpack/inspect/node.rb +286 -0
- data/lib/msgpack/inspect/simple_yaml_dumper.rb +8 -0
- data/lib/msgpack/inspect/streamer.rb +356 -0
- data/lib/msgpack/inspect/version.rb +1 -1
- data/mrbgem.rake +13 -0
- data/mrblib/msgpack-inspect.rb +66 -0
- data/mrblib/msgpack/inspect.rb +9 -0
- data/mrblib/msgpack/inspect/inspector.rb +1 -0
- data/mrblib/msgpack/inspect/node.rb +1 -0
- data/mrblib/msgpack/inspect/streamer.rb +1 -0
- data/mrblib/msgpack/inspect/version.rb +1 -0
- data/tools/msgpack-inspect/msgpack-inspect.c +33 -0
- metadata +18 -2
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
- format: fixarray
|
3
|
+
header: "ff"
|
4
|
+
length: 3
|
5
|
+
children:
|
6
|
+
- format: string
|
7
|
+
header: "e0"
|
8
|
+
length: 10
|
9
|
+
data: "0102030405060708090a"
|
10
|
+
value: "aaaaaaaaaa"
|
11
|
+
- format: int
|
12
|
+
header: "10"
|
13
|
+
data: "10"
|
14
|
+
value: 10
|
15
|
+
- format: nil
|
16
|
+
header: "a0"
|
17
|
+
data: "a0"
|
18
|
+
value: null
|
19
|
+
- format: fixmap
|
20
|
+
header: "ff"
|
21
|
+
length: 2
|
22
|
+
children:
|
23
|
+
- key:
|
24
|
+
format: nil
|
25
|
+
data: "a0"
|
26
|
+
value:
|
27
|
+
format: nil
|
28
|
+
data: "a0"
|
29
|
+
- key:
|
30
|
+
format: nil
|
31
|
+
data: "a0"
|
32
|
+
value:
|
33
|
+
format: nil
|
34
|
+
data: "a0"
|
@@ -1,81 +1,69 @@
|
|
1
1
|
module MessagePack
|
2
2
|
module Inspect
|
3
|
-
# Node(Hash)
|
4
|
-
# header: hex (binary)
|
5
|
-
# exttype: hex (value)
|
6
|
-
# length: numeric
|
7
|
-
# data: hex
|
8
|
-
# value: object
|
9
|
-
# children: (array of Node for array, array of Hash, which has keys of :key and :value for map)
|
10
|
-
|
11
3
|
class Inspector
|
12
|
-
FORMATS = [:yaml, :json]
|
13
|
-
|
14
|
-
attr_reader :data
|
4
|
+
FORMATS = [:yaml, :json, :jsonl, nil] # nil is for test (without stream dump)
|
15
5
|
|
16
|
-
def initialize(io)
|
6
|
+
def initialize(io, format = :yaml, opt)
|
7
|
+
# return_values: false, output_io: STDOUT
|
17
8
|
@io = io
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
@format = format
|
10
|
+
@streamer = MessagePack::Inspect::Streamer.get(@format)
|
11
|
+
@return_values = opt.fetch(:return_values, false)
|
12
|
+
@output_io = opt.fetch(:output_io, STDOUT)
|
22
13
|
end
|
23
14
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
{format: fmt, header: hex(header), length: nil, children: []}
|
36
|
-
when :fixstr, :str8, :str16, :str32
|
37
|
-
{format: fmt, header: hex(header), length: nil, data: nil, value: nil}
|
38
|
-
when :nil
|
39
|
-
{format: fmt, header: hex(header), data: hex(header), value: nil}
|
40
|
-
when :false
|
41
|
-
{format: fmt, header: hex(header), data: hex(header), value: false}
|
42
|
-
when :true
|
43
|
-
{format: fmt, header: hex(header), data: hex(header), value: true}
|
44
|
-
when :bin8, :bin16, :bin32
|
45
|
-
{format: fmt, header: hex(header), length: nil, data: nil, value: nil}
|
46
|
-
when :ext8, :ext16, :ext32, :fixext1, :fixext2, :fixext4, :fixext8, :fixext16
|
47
|
-
{format: fmt, header: hex(header), exttype: nil, length: nil, data: nil} # value will be set if MessagePack is installed
|
48
|
-
when :float32, :float64
|
49
|
-
{format: fmt, header: hex(header), data: nil, value: nil}
|
50
|
-
when :never_used
|
51
|
-
{format: fmt, header: hex(header), data: hex(header), error: "msgpack format 'NEVER USED' specified"}
|
52
|
-
else
|
53
|
-
raise "unknown format specifier: #{fmt}"
|
15
|
+
def inspect
|
16
|
+
data = []
|
17
|
+
@streamer.objects(@output_io, 0) do
|
18
|
+
i = 0
|
19
|
+
until @io.eof?
|
20
|
+
@streamer.object(@output_io, 1, i) do
|
21
|
+
obj = dig(1)
|
22
|
+
data << obj if @return_values
|
23
|
+
end
|
24
|
+
i += 1
|
25
|
+
end
|
54
26
|
end
|
27
|
+
@return_values ? data : nil
|
55
28
|
end
|
56
29
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
30
|
+
def dig(depth, heading = true)
|
31
|
+
header_byte = @io.read(1)
|
32
|
+
# TODO: error handling for header_byte:nil or raised exception
|
33
|
+
header = header_byte.b
|
34
|
+
fmt = parse_header(header)
|
35
|
+
node = MessagePack::Inspect::Node.new(fmt, header)
|
36
|
+
node.extend @streamer
|
37
|
+
node.io = @output_io
|
38
|
+
node.depth = depth # Streamer#depth=
|
39
|
+
node.heading = heading
|
40
|
+
|
41
|
+
node.attributes(@io)
|
42
|
+
|
43
|
+
if node.is_array?
|
44
|
+
node.elements do |i|
|
45
|
+
@streamer.object(@output_io, depth + 2, i) do
|
46
|
+
obj = dig(depth + 2) # children -> array
|
47
|
+
node << obj if @return_values
|
48
|
+
end
|
49
|
+
end
|
50
|
+
elsif node.is_map?
|
51
|
+
node.elements do |i|
|
52
|
+
key = node.element_key do
|
53
|
+
@streamer.object(@output_io, depth + 3, 0) do
|
54
|
+
dig(depth + 3, false) # chilren -> array -> key
|
55
|
+
end
|
56
|
+
end
|
57
|
+
value = node.element_value do
|
58
|
+
@streamer.object(@output_io, depth + 3, 0) do
|
59
|
+
dig(depth + 3, false) # children -> array -> value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
node[key] = value if @return_values
|
69
63
|
end
|
70
|
-
else
|
71
|
-
raise "unknown format: #{format}"
|
72
64
|
end
|
73
|
-
end
|
74
65
|
|
75
|
-
|
76
|
-
header = io.read(1).b
|
77
|
-
fmt = parse_header(header)
|
78
|
-
yield generate(io, fmt, header, node(fmt, header))
|
66
|
+
node
|
79
67
|
end
|
80
68
|
|
81
69
|
HEADER_FIXINT_POSITIVE = Range.new(0x00, 0x7f)
|
@@ -159,228 +147,6 @@ module MessagePack
|
|
159
147
|
raise "never reach here."
|
160
148
|
end
|
161
149
|
end
|
162
|
-
|
163
|
-
def generate_array(io, fmt, header, current)
|
164
|
-
length = case fmt
|
165
|
-
when :fixarray
|
166
|
-
header.unpack('C').first & 0x0f
|
167
|
-
when :array16
|
168
|
-
io.read(2).unpack('n').first
|
169
|
-
when :array32
|
170
|
-
io.read(4).unpack('N').first
|
171
|
-
else
|
172
|
-
raise "unknown array fmt #{fmt}"
|
173
|
-
end
|
174
|
-
current[:length] = length
|
175
|
-
length.times do |i|
|
176
|
-
dig(io){|obj| current[:children] << obj }
|
177
|
-
end
|
178
|
-
current
|
179
|
-
end
|
180
|
-
|
181
|
-
def generate_map(io, fmt, header, current)
|
182
|
-
length = case fmt
|
183
|
-
when :fixmap
|
184
|
-
header.unpack('C').first & 0x0f
|
185
|
-
when :map16
|
186
|
-
io.read(2).unpack('n').first
|
187
|
-
when :map32
|
188
|
-
io.read(4).unpack('N').first
|
189
|
-
else
|
190
|
-
raise "unknown map fmt #{fmt}"
|
191
|
-
end
|
192
|
-
current[:length] = length
|
193
|
-
length.times do |i|
|
194
|
-
pair = {}
|
195
|
-
dig(io){|key| pair[:key] = key }
|
196
|
-
dig(io){|value| pair[:value] = value }
|
197
|
-
current[:children] << pair
|
198
|
-
end
|
199
|
-
current
|
200
|
-
end
|
201
|
-
|
202
|
-
MAX_INT16 = 2 ** 16
|
203
|
-
MAX_INT32 = 2 ** 32
|
204
|
-
MAX_INT64 = 2 ** 64
|
205
|
-
|
206
|
-
def generate_int(io, fmt, header, current)
|
207
|
-
if fmt == :fixint
|
208
|
-
current[:data] = hex(header)
|
209
|
-
v = header.unpack('C').first
|
210
|
-
if v & 0b11100000 > 0 # negative fixint
|
211
|
-
current[:value] = header.unpack('c').first
|
212
|
-
else # positive fixint
|
213
|
-
current[:value] = header.unpack('C').first
|
214
|
-
end
|
215
|
-
return current
|
216
|
-
end
|
217
|
-
|
218
|
-
case fmt
|
219
|
-
when :uint8
|
220
|
-
v = io.read(1)
|
221
|
-
current[:data] = hex(v)
|
222
|
-
current[:value] = v.unpack('C').first
|
223
|
-
when :uint16
|
224
|
-
v = io.read(2)
|
225
|
-
current[:data] = hex(v)
|
226
|
-
current[:value] = v.unpack('n').first
|
227
|
-
when :uint32
|
228
|
-
v = io.read(4)
|
229
|
-
current[:data] = hex(v)
|
230
|
-
current[:value] = v.unpack('N').first
|
231
|
-
when :uint64
|
232
|
-
v1 = io.read(4)
|
233
|
-
v2 = io.read(4)
|
234
|
-
current[:data] = hex(v1) + hex(v2)
|
235
|
-
current[:value] = (v1.unpack('N').first << 32) | v2.unpack('N').first
|
236
|
-
when :int8
|
237
|
-
v = io.read(1)
|
238
|
-
current[:data] = hex(v)
|
239
|
-
current[:value] = v.unpack('c').first
|
240
|
-
when :int16
|
241
|
-
v = io.read(2)
|
242
|
-
current[:data] = hex(v)
|
243
|
-
n = v.unpack('n').first
|
244
|
-
if (n & 0x8000) > 0 # negative
|
245
|
-
current[:value] = n - MAX_INT16
|
246
|
-
else
|
247
|
-
current[:value] = n
|
248
|
-
end
|
249
|
-
when :int32
|
250
|
-
v = io.read(4)
|
251
|
-
current[:data] = hex(v)
|
252
|
-
n = v.unpack('N').first
|
253
|
-
if n & 0x80000000 > 0 # negative
|
254
|
-
current[:value] = n - MAX_INT32
|
255
|
-
else
|
256
|
-
current[:value] = n
|
257
|
-
end
|
258
|
-
when :int64
|
259
|
-
v1 = io.read(4)
|
260
|
-
v2 = io.read(4)
|
261
|
-
current[:data] = hex(v1) + hex(v2)
|
262
|
-
n = (v1.unpack('N').first << 32) | v2.unpack('N').first
|
263
|
-
if n & 0x8000_0000_0000_0000 > 0 # negative
|
264
|
-
current[:value] = n - MAX_INT64
|
265
|
-
else
|
266
|
-
current[:value] = n
|
267
|
-
end
|
268
|
-
else
|
269
|
-
raise "unknown int format #{fmt}"
|
270
|
-
end
|
271
|
-
current
|
272
|
-
end
|
273
|
-
|
274
|
-
def generate_float(io, fmt, header, current)
|
275
|
-
case fmt
|
276
|
-
when :float32
|
277
|
-
v = io.read(4)
|
278
|
-
current[:data] = hex(v)
|
279
|
-
current[:value] = v.unpack('g').first
|
280
|
-
when :float64
|
281
|
-
v = io.read(8)
|
282
|
-
current[:data] = hex(v)
|
283
|
-
current[:value] = v.unpack('G').first
|
284
|
-
else
|
285
|
-
raise "unknown float format #{fmt}"
|
286
|
-
end
|
287
|
-
current
|
288
|
-
end
|
289
|
-
|
290
|
-
def generate_string(io, fmt, header, current)
|
291
|
-
length = case fmt
|
292
|
-
when :fixstr
|
293
|
-
header.unpack('C').first & 0b00011111
|
294
|
-
when :str8, :bin8
|
295
|
-
io.read(1).unpack('C').first
|
296
|
-
when :str16, :bin16
|
297
|
-
io.read(2).unpack('n').first
|
298
|
-
when :str32, :bin32
|
299
|
-
io.read(4).unpack('N').first
|
300
|
-
else
|
301
|
-
raise "unknown string format #{fmt}"
|
302
|
-
end
|
303
|
-
current[:length] = length
|
304
|
-
v = io.read(length)
|
305
|
-
current[:data] = hex(v)
|
306
|
-
if [:fixstr, :str8, :str16, :str32].include?(fmt)
|
307
|
-
begin
|
308
|
-
current[:value] = v.force_encoding('UTF-8')
|
309
|
-
rescue
|
310
|
-
current[:error] = $!.message
|
311
|
-
end
|
312
|
-
else
|
313
|
-
current[:value] = v.b
|
314
|
-
end
|
315
|
-
current
|
316
|
-
end
|
317
|
-
|
318
|
-
begin
|
319
|
-
require 'msgpack'
|
320
|
-
rescue LoadError
|
321
|
-
# ignore
|
322
|
-
end
|
323
|
-
MSGPACK_LOADED = MessagePack.const_defined?('Unpacker')
|
324
|
-
|
325
|
-
def generate_ext(io, fmt, header, current)
|
326
|
-
data = ''.b
|
327
|
-
length = case fmt
|
328
|
-
when :fixext1 then 1
|
329
|
-
when :fixext2 then 2
|
330
|
-
when :fixext4 then 4
|
331
|
-
when :fixext8 then 8
|
332
|
-
when :fixext16 then 16
|
333
|
-
when :ext8
|
334
|
-
v = io.read(1)
|
335
|
-
data << v
|
336
|
-
v.unpack('C').first
|
337
|
-
when :ext16
|
338
|
-
v = io.read(2)
|
339
|
-
data << v
|
340
|
-
v.unpack('n').first
|
341
|
-
when :ext32
|
342
|
-
v = io.read(4)
|
343
|
-
data << v
|
344
|
-
v.unpack('N').first
|
345
|
-
else
|
346
|
-
raise "unknown ext format #{fmt}"
|
347
|
-
end
|
348
|
-
v = io.read(1)
|
349
|
-
data << v
|
350
|
-
type = v.unpack('c').first
|
351
|
-
current[:length] = length
|
352
|
-
current[:exttype] = type
|
353
|
-
val = io.read(length)
|
354
|
-
data << val
|
355
|
-
current[:data] = hex(val)
|
356
|
-
if MSGPACK_LOADED
|
357
|
-
current[:value] = MessagePack.unpack(val)
|
358
|
-
end
|
359
|
-
current
|
360
|
-
end
|
361
|
-
|
362
|
-
def generate(io, fmt, header, current)
|
363
|
-
case fmt
|
364
|
-
when :fixarray, :array16, :array32
|
365
|
-
generate_array(io, fmt, header, current)
|
366
|
-
when :fixmap, :map16, :map32
|
367
|
-
generate_map(io, fmt, header, current)
|
368
|
-
when :nil, :false, :true, :never_used
|
369
|
-
# nothing to do...
|
370
|
-
when :fixint, :uint8, :uint16, :uint32, :uint64, :int8, :int16, :int32, :int64
|
371
|
-
generate_int(io, fmt, header, current)
|
372
|
-
when :float32, :float64
|
373
|
-
generate_float(io, fmt, header, current)
|
374
|
-
when :fixstr, :str8, :str16, :str32, :bin8, :bin16, :bin32
|
375
|
-
generate_string(io, fmt, header, current)
|
376
|
-
when :ext8, :ext16, :ext32, :fixext1, :fixext2, :fixext4, :fixext8, :fixext16
|
377
|
-
generate_ext(io, fmt, header, current)
|
378
|
-
else
|
379
|
-
raise "unknown format #{fmt}"
|
380
|
-
end
|
381
|
-
|
382
|
-
current
|
383
|
-
end
|
384
150
|
end
|
385
151
|
end
|
386
152
|
end
|
@@ -0,0 +1,286 @@
|
|
1
|
+
module MessagePack
|
2
|
+
module Inspect
|
3
|
+
class Node
|
4
|
+
# header: hex (binary)
|
5
|
+
# exttype: hex (value)
|
6
|
+
# length: numeric
|
7
|
+
# data: hex
|
8
|
+
# value: object
|
9
|
+
# children: (array of Node for array, array of Hash, which has keys of :key and :value for map)
|
10
|
+
attr_accessor :format, :header, :length, :exttype, :data, :value, :children, :error
|
11
|
+
attr_accessor :io, :depth, :heading
|
12
|
+
|
13
|
+
FORMATS = [
|
14
|
+
:fixint, :uint8, :uint16, :uint32, :uint64, :int8, :int16, :int32, :int64,
|
15
|
+
:fixmap, :map16, :map32,
|
16
|
+
:fixarray, :array16, :array32,
|
17
|
+
:fixstr, :str8, :str16, :str32,
|
18
|
+
:nil, :false, :true,
|
19
|
+
:bin8, :bin16, :bin32,
|
20
|
+
:ext8, :ext16, :ext32, :fixext1, :fixext2, :fixext4, :fixext8, :fixext16,
|
21
|
+
:float32, :float64,
|
22
|
+
:never_used,
|
23
|
+
]
|
24
|
+
ARRAYS = [:fixarray, :array16, :array32]
|
25
|
+
MAPS = [:fixmap, :map16, :map32]
|
26
|
+
|
27
|
+
def initialize(format, header)
|
28
|
+
raise "unknown format specifier: #{format}" unless FORMATS.include?(format)
|
29
|
+
@format = format
|
30
|
+
@header = header # call #hex to dump
|
31
|
+
@length = @exttype = @data = @value = @children = @error = nil
|
32
|
+
|
33
|
+
case @format
|
34
|
+
when :fixmap, :map16, :map32, :fixarray, :array16, :array32
|
35
|
+
@children = []
|
36
|
+
when :nil
|
37
|
+
@data = hex(header)
|
38
|
+
@value = nil
|
39
|
+
when :false
|
40
|
+
@data = hex(header)
|
41
|
+
@value = false
|
42
|
+
when :true
|
43
|
+
@data = hex(header)
|
44
|
+
@value = true
|
45
|
+
when :never_used
|
46
|
+
@data = hex(header)
|
47
|
+
@error = "msgpack format 'NEVER USED' specified"
|
48
|
+
end
|
49
|
+
|
50
|
+
@first_line = true
|
51
|
+
@first_obj = true
|
52
|
+
@first_kv_pair = true
|
53
|
+
end
|
54
|
+
|
55
|
+
def hex(str)
|
56
|
+
str.unpack("H*").first
|
57
|
+
end
|
58
|
+
|
59
|
+
def elements(&block)
|
60
|
+
@length.times do |i|
|
61
|
+
yield i
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def element_key
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
|
69
|
+
def element_value
|
70
|
+
yield
|
71
|
+
end
|
72
|
+
|
73
|
+
def attributes(io)
|
74
|
+
# read attributes from io
|
75
|
+
case @format
|
76
|
+
when :fixarray, :array16, :array32
|
77
|
+
attributes_array(io)
|
78
|
+
when :fixmap, :map16, :map32
|
79
|
+
attributes_map(io)
|
80
|
+
when :nil, :false, :true, :never_used
|
81
|
+
# nothing to do...
|
82
|
+
when :fixint, :uint8, :uint16, :uint32, :uint64, :int8, :int16, :int32, :int64
|
83
|
+
attributes_int(io)
|
84
|
+
when :float32, :float64
|
85
|
+
attributes_float(io)
|
86
|
+
when :fixstr, :str8, :str16, :str32, :bin8, :bin16, :bin32
|
87
|
+
attributes_string(io)
|
88
|
+
when :ext8, :ext16, :ext32, :fixext1, :fixext2, :fixext4, :fixext8, :fixext16
|
89
|
+
attributes_ext(io)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def attributes_array(io)
|
94
|
+
@length = case @format
|
95
|
+
when :fixarray
|
96
|
+
@header.unpack('C').first & 0x0f
|
97
|
+
when :array16
|
98
|
+
io.read(2).unpack('n').first
|
99
|
+
when :array32
|
100
|
+
io.read(4).unpack('N').first
|
101
|
+
else
|
102
|
+
raise "unknown array fmt #{@format}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def attributes_map(io)
|
107
|
+
@length = case @format
|
108
|
+
when :fixmap
|
109
|
+
@header.unpack('C').first & 0x0f
|
110
|
+
when :map16
|
111
|
+
io.read(2).unpack('n').first
|
112
|
+
when :map32
|
113
|
+
io.read(4).unpack('N').first
|
114
|
+
else
|
115
|
+
raise "unknown map fmt #{@format}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
MAX_INT16 = 2 ** 16
|
120
|
+
MAX_INT32 = 2 ** 32
|
121
|
+
MAX_INT64 = 2 ** 64
|
122
|
+
|
123
|
+
def attributes_int(io)
|
124
|
+
if @format == :fixint
|
125
|
+
@data = hex(@header)
|
126
|
+
v = @header.unpack('C').first
|
127
|
+
@value = if v & 0b11100000 > 0 # negative fixint
|
128
|
+
@header.unpack('c').first
|
129
|
+
else # positive fixint
|
130
|
+
@header.unpack('C').first
|
131
|
+
end
|
132
|
+
return
|
133
|
+
end
|
134
|
+
|
135
|
+
case @format
|
136
|
+
when :uint8
|
137
|
+
v = io.read(1)
|
138
|
+
@data = hex(v)
|
139
|
+
@value = v.unpack('C').first
|
140
|
+
when :uint16
|
141
|
+
v = io.read(2)
|
142
|
+
@data = hex(v)
|
143
|
+
@value = v.unpack('n').first
|
144
|
+
when :uint32
|
145
|
+
v = io.read(4)
|
146
|
+
@data = hex(v)
|
147
|
+
@value = v.unpack('N').first
|
148
|
+
when :uint64
|
149
|
+
v1 = io.read(4)
|
150
|
+
v2 = io.read(4)
|
151
|
+
@data = hex(v1) + hex(v2)
|
152
|
+
@value = (v1.unpack('N').first << 32) | v2.unpack('N').first
|
153
|
+
when :int8
|
154
|
+
v = io.read(1)
|
155
|
+
@data = hex(v)
|
156
|
+
@value = v.unpack('c').first
|
157
|
+
when :int16
|
158
|
+
v = io.read(2)
|
159
|
+
@data = hex(v)
|
160
|
+
n = v.unpack('n').first
|
161
|
+
@value = if (n & 0x8000) > 0 # negative
|
162
|
+
n - MAX_INT16
|
163
|
+
else
|
164
|
+
n
|
165
|
+
end
|
166
|
+
when :int32
|
167
|
+
v = io.read(4)
|
168
|
+
@data = hex(v)
|
169
|
+
n = v.unpack('N').first
|
170
|
+
@value = if n & 0x80000000 > 0 # negative
|
171
|
+
n - MAX_INT32
|
172
|
+
else
|
173
|
+
n
|
174
|
+
end
|
175
|
+
when :int64
|
176
|
+
v1 = io.read(4)
|
177
|
+
v2 = io.read(4)
|
178
|
+
@data = hex(v1) + hex(v2)
|
179
|
+
n = (v1.unpack('N').first << 32) | v2.unpack('N').first
|
180
|
+
@value = if n & 0x8000_0000_0000_0000 > 0 # negative
|
181
|
+
n - MAX_INT64
|
182
|
+
else
|
183
|
+
n
|
184
|
+
end
|
185
|
+
else
|
186
|
+
raise "unknown int format #{@format}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def attributes_float(io)
|
191
|
+
case @format
|
192
|
+
when :float32
|
193
|
+
v = io.read(4)
|
194
|
+
@data = hex(v)
|
195
|
+
@value = v.unpack('g').first
|
196
|
+
when :float64
|
197
|
+
v = io.read(8)
|
198
|
+
@data = hex(v)
|
199
|
+
@value = v.unpack('G').first
|
200
|
+
else
|
201
|
+
raise "unknown float format #{@format}"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def attributes_string(io)
|
206
|
+
@length = case @format
|
207
|
+
when :fixstr
|
208
|
+
@header.unpack('C').first & 0b00011111
|
209
|
+
when :str8, :bin8
|
210
|
+
io.read(1).unpack('C').first
|
211
|
+
when :str16, :bin16
|
212
|
+
io.read(2).unpack('n').first
|
213
|
+
when :str32, :bin32
|
214
|
+
io.read(4).unpack('N').first
|
215
|
+
else
|
216
|
+
raise "unknown string format #{@format}"
|
217
|
+
end
|
218
|
+
v = io.read(@length)
|
219
|
+
@data = hex(v)
|
220
|
+
if [:fixstr, :str8, :str16, :str32].include?(@format)
|
221
|
+
begin
|
222
|
+
@value = v.force_encoding('UTF-8')
|
223
|
+
rescue
|
224
|
+
@error = $!.message
|
225
|
+
end
|
226
|
+
else
|
227
|
+
@value = v.b
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
MSGPACK_LOADED = MessagePack.const_defined?('Unpacker')
|
232
|
+
|
233
|
+
def attributes_ext(io)
|
234
|
+
data = ''.b
|
235
|
+
@length = case @format
|
236
|
+
when :fixext1 then 1
|
237
|
+
when :fixext2 then 2
|
238
|
+
when :fixext4 then 4
|
239
|
+
when :fixext8 then 8
|
240
|
+
when :fixext16 then 16
|
241
|
+
when :ext8
|
242
|
+
v = io.read(1)
|
243
|
+
data << v
|
244
|
+
v.unpack('C').first
|
245
|
+
when :ext16
|
246
|
+
v = io.read(2)
|
247
|
+
data << v
|
248
|
+
v.unpack('n').first
|
249
|
+
when :ext32
|
250
|
+
v = io.read(4)
|
251
|
+
data << v
|
252
|
+
v.unpack('N').first
|
253
|
+
else
|
254
|
+
raise "unknown ext format #{@format}"
|
255
|
+
end
|
256
|
+
v = io.read(1)
|
257
|
+
@exttype = v.unpack('c').first
|
258
|
+
val = io.read(@length)
|
259
|
+
@data = hex(val)
|
260
|
+
@value = if MSGPACK_LOADED
|
261
|
+
MessagePack.unpack(val)
|
262
|
+
else
|
263
|
+
nil
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def is_array?
|
268
|
+
ARRAYS.include?(@format)
|
269
|
+
end
|
270
|
+
|
271
|
+
def is_map?
|
272
|
+
MAPS.include?(@format)
|
273
|
+
end
|
274
|
+
|
275
|
+
def <<(child)
|
276
|
+
raise "adding child object to non-array object" unless is_array?
|
277
|
+
@children << child
|
278
|
+
end
|
279
|
+
|
280
|
+
def []=(key, value)
|
281
|
+
raise "adding key-value objects to non-map object" unless is_map?
|
282
|
+
@children << {key => value}
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|