hessian2 2.0.2 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +10 -10
- data/README.md +197 -197
- data/hessian2.gemspec +0 -2
- data/lib/hessian2/client.rb +57 -50
- data/lib/hessian2/constants.rb +164 -164
- data/lib/hessian2/fault.rb +3 -3
- data/lib/hessian2/handler.rb +18 -18
- data/lib/hessian2/hessian_client.rb +3 -3
- data/lib/hessian2/parser.rb +619 -619
- data/lib/hessian2/type_wrapper.rb +49 -49
- data/lib/hessian2/version.rb +3 -3
- data/lib/hessian2/writer.rb +499 -499
- data/lib/hessian2.rb +14 -14
- data/spec/binary_spec.rb +51 -51
- data/spec/boolean_spec.rb +26 -26
- data/spec/class_wrapper_spec.rb +52 -52
- data/spec/create_monkeys.rb +14 -14
- data/spec/date_spec.rb +45 -45
- data/spec/double_spec.rb +78 -78
- data/spec/int_spec.rb +54 -54
- data/spec/list_spec.rb +66 -66
- data/spec/long_spec.rb +68 -68
- data/spec/map_spec.rb +36 -36
- data/spec/null_spec.rb +17 -17
- data/spec/object_spec.rb +78 -78
- data/spec/ref_spec.rb +43 -43
- data/spec/spec_helper.rb +23 -23
- data/spec/string_spec.rb +61 -61
- data/spec/struct_wrapper_spec.rb +47 -47
- data/spec/type_wrapper_spec.rb +102 -102
- data/test/app.rb +24 -24
- data/test/async/em_http_asleep.rb +25 -25
- data/test/async/em_http_sleep.rb +25 -25
- data/test/async/monkey.asleep.rb +27 -27
- data/test/async/mysql2_aquery.rb +37 -37
- data/test/fault/monkey.undefined_method.rb +5 -5
- data/test/fault/monkey.wrong_arguments.rb +5 -5
- data/test/fiber_concurrency/em_http_asleep.rb +17 -17
- data/test/fiber_concurrency/em_http_sleep.rb +17 -17
- data/test/fiber_concurrency/monkey.asleep.fiber_aware.rb +18 -18
- data/test/fiber_concurrency/mysql2_query.rb +29 -29
- data/test/fiber_concurrency/net_http_asleep.rb +19 -19
- data/test/fiber_concurrency/net_http_sleep.rb +19 -19
- data/test/fibered_rainbows/Gemfile +15 -15
- data/test/fibered_rainbows/config.ru +11 -11
- data/test/fibered_rainbows/rainbows.rb +13 -13
- data/test/monkey_service.rb +16 -16
- data/test/prepare.rb +7 -7
- data/test/thread_concurrency/active_record_execute.rb +29 -29
- data/test/thread_concurrency/monkey.asleep.rb +22 -22
- data/test/thread_concurrency/net_http_asleep.rb +24 -24
- data/test/thread_concurrency/net_http_sleep.rb +24 -24
- data/test/threaded_rainbows/Gemfile +13 -13
- data/test/threaded_rainbows/config.ru +9 -9
- data/test/threaded_rainbows/rainbows.rb +13 -13
- metadata +4 -74
data/lib/hessian2/parser.rb
CHANGED
@@ -1,619 +1,619 @@
|
|
1
|
-
require 'hessian2/constants'
|
2
|
-
require 'hessian2/fault'
|
3
|
-
|
4
|
-
module Hessian2
|
5
|
-
module Parser
|
6
|
-
include Constants
|
7
|
-
|
8
|
-
def parse_rpc(data)
|
9
|
-
bytes = data.each_byte
|
10
|
-
bc = bytes.next
|
11
|
-
if bc == 0x48 # skip hessian version
|
12
|
-
2.times{ bytes.next }
|
13
|
-
bc = bytes.next
|
14
|
-
end
|
15
|
-
|
16
|
-
case bc
|
17
|
-
when 0x43 # rpc call ('C')
|
18
|
-
method = parse_string(bytes)
|
19
|
-
refs, cdefs = [], []
|
20
|
-
args = [].tap do |arr|
|
21
|
-
parse_int(bytes).times{ arr << parse_bytes(bytes, nil, {}, refs, cdefs) }
|
22
|
-
end
|
23
|
-
[ method, *args ]
|
24
|
-
when 0x46 # fault ('F')
|
25
|
-
fault = parse_bytes(bytes)
|
26
|
-
code, message = fault['code'], fault['message']
|
27
|
-
raise Fault.new, code == 'RuntimeError' ? message : "#{code} - #{message}"
|
28
|
-
when 0x52 # rpc result ('R')
|
29
|
-
parse_bytes(bytes)
|
30
|
-
else
|
31
|
-
raise data
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
def parse(data, klass = nil, options = {})
|
37
|
-
parse_bytes(data.each_byte, klass, options)
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
def parse_bytes(bytes, klass = nil, options = {}, refs = [], cdefs = [])
|
42
|
-
bc = bytes.next
|
43
|
-
case bc
|
44
|
-
when 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
45
|
-
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
46
|
-
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
47
|
-
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
48
|
-
# 0x00 - 0x1f utf-8 string length 0-31
|
49
|
-
read_string_direct(bytes, bc)
|
50
|
-
when 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
51
|
-
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
52
|
-
# 0x20 - 0x2f binary data length 0-15
|
53
|
-
read_binary_direct(bytes, bc)
|
54
|
-
when 0x30, 0x31, 0x32, 0x33
|
55
|
-
# 0x30 - 0x33 utf-8 string length 0-1023
|
56
|
-
read_string_short(bytes, bc)
|
57
|
-
when 0x34, 0x35, 0x36, 0x37
|
58
|
-
# 0x34 - 0x37 binary data length 0-1023
|
59
|
-
read_binary_short(bytes, bc)
|
60
|
-
when 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
|
61
|
-
# 0x38 - 0x3f three-octet compact long (-x40000 to x3ffff)
|
62
|
-
read_long_short_zero(bytes, bc)
|
63
|
-
when 0x41 # 8-bit binary data non-final chunk ('A')
|
64
|
-
read_binary_chunk(bytes)
|
65
|
-
when 0x42 # 8-bit binary data final chunk ('B')
|
66
|
-
read_binary(bytes)
|
67
|
-
when 0x43 # object type definition ('C')
|
68
|
-
name = parse_string(bytes)
|
69
|
-
fields = []
|
70
|
-
|
71
|
-
parse_int(bytes).times do
|
72
|
-
fields << parse_string(bytes)
|
73
|
-
end
|
74
|
-
cdefs << Struct.new(*fields.map{|f| f.to_sym})
|
75
|
-
|
76
|
-
parse_bytes(bytes, klass, options, refs, cdefs)
|
77
|
-
when 0x44 # 64-bit IEEE encoded double ('D')
|
78
|
-
read_double(bytes)
|
79
|
-
when 0x46 # boolean false ('F')
|
80
|
-
false
|
81
|
-
when 0x48 # untyped map ('H')
|
82
|
-
read_hash(bytes, klass, options, refs, cdefs)
|
83
|
-
when 0x49 # 32-bit signed integer ('I')
|
84
|
-
read_int(bytes)
|
85
|
-
when 0x4a # 64-bit UTC millisecond date
|
86
|
-
read_date(bytes)
|
87
|
-
when 0x4b # 32-bit UTC minute date
|
88
|
-
read_date_minute(bytes)
|
89
|
-
when 0x4c # 64-bit signed long integer ('L')
|
90
|
-
read_long(bytes)
|
91
|
-
when 0x4d # map with type ('M')
|
92
|
-
parse_type(bytes)
|
93
|
-
read_hash(bytes, klass, options, refs, cdefs)
|
94
|
-
when 0x4e # null ('N')
|
95
|
-
nil
|
96
|
-
when 0x4f # object instance ('O')
|
97
|
-
cdef = cdefs[parse_int(bytes)]
|
98
|
-
val = cdef.new
|
99
|
-
refs << val # store a value reference first
|
100
|
-
val.members.each do |sym|
|
101
|
-
val[sym] = parse_bytes(bytes, klass, options, refs, cdefs)
|
102
|
-
end
|
103
|
-
|
104
|
-
val
|
105
|
-
when 0x51 # reference to map/list/object - integer ('Q')
|
106
|
-
refs[parse_int(bytes)]
|
107
|
-
when 0x52 # utf-8 string non-final chunk ('R')
|
108
|
-
read_string_chunk(bytes)
|
109
|
-
when 0x53 # utf-8 string final chunk ('S')
|
110
|
-
read_string(bytes)
|
111
|
-
when 0x54 # boolean true ('T')
|
112
|
-
true
|
113
|
-
when 0x55 # variable-length list/vector ('U')
|
114
|
-
parse_type(bytes)
|
115
|
-
|
116
|
-
is_struct, klass = read_klass(klass)
|
117
|
-
|
118
|
-
if is_struct
|
119
|
-
arr = []
|
120
|
-
while bytes.peek != BC_END
|
121
|
-
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
122
|
-
end
|
123
|
-
|
124
|
-
val = klass.new(*arr)
|
125
|
-
refs << val
|
126
|
-
else
|
127
|
-
val = []
|
128
|
-
refs << val # store a value reference first
|
129
|
-
while bytes.peek != BC_END
|
130
|
-
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
bytes.next
|
135
|
-
val
|
136
|
-
when 0x56 # fixed-length list/vector ('V')
|
137
|
-
parse_type(bytes)
|
138
|
-
|
139
|
-
is_struct, klass = read_klass(klass)
|
140
|
-
|
141
|
-
if is_struct
|
142
|
-
arr = []
|
143
|
-
parse_int(bytes).times do
|
144
|
-
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
145
|
-
end
|
146
|
-
|
147
|
-
val = klass.new(*arr)
|
148
|
-
refs << val
|
149
|
-
else
|
150
|
-
val = []
|
151
|
-
refs << val # store a value reference
|
152
|
-
parse_int(bytes).times do
|
153
|
-
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
val
|
158
|
-
when 0x57 # variable-length untyped list/vector ('W')
|
159
|
-
is_struct, klass = read_klass(klass)
|
160
|
-
|
161
|
-
if is_struct
|
162
|
-
arr = []
|
163
|
-
while bytes.peek != BC_END
|
164
|
-
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
165
|
-
end
|
166
|
-
|
167
|
-
val = klass.new(*arr)
|
168
|
-
refs << val
|
169
|
-
else
|
170
|
-
val = []
|
171
|
-
refs << val # store a value reference first
|
172
|
-
while bytes.peek != BC_END
|
173
|
-
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
bytes.next
|
178
|
-
val
|
179
|
-
when 0x58 # fixed-length untyped list/vector ('X')
|
180
|
-
is_struct, klass = read_klass(klass)
|
181
|
-
|
182
|
-
if is_struct
|
183
|
-
arr = []
|
184
|
-
parse_int(bytes).times do
|
185
|
-
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
186
|
-
end
|
187
|
-
|
188
|
-
val = klass.new(*arr)
|
189
|
-
refs << val
|
190
|
-
else
|
191
|
-
val = []
|
192
|
-
refs << val # store a value reference first
|
193
|
-
parse_int(bytes).times do
|
194
|
-
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
val
|
199
|
-
when 0x59 # long encoded as 32-bit int ('Y')
|
200
|
-
read_int(bytes)
|
201
|
-
when 0x5b # double 0.0
|
202
|
-
0
|
203
|
-
when 0x5c # double 1.0
|
204
|
-
1
|
205
|
-
when 0x5d # double represented as byte (-128.0 to 127.0)
|
206
|
-
read_double_direct(bytes)
|
207
|
-
when 0x5e # double represented as short (-32768.0 to 32767.0)
|
208
|
-
read_double_short(bytes)
|
209
|
-
when 0x5f # double represented as float
|
210
|
-
read_double_mill(bytes)
|
211
|
-
when 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
212
|
-
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f
|
213
|
-
# 0x60 - 0x6f object with direct type
|
214
|
-
cdef = cdefs[bc - BC_OBJECT_DIRECT]
|
215
|
-
val = cdef.new
|
216
|
-
refs << val # store a value reference first
|
217
|
-
val.members.each do |sym|
|
218
|
-
val[sym] = parse_bytes(bytes, klass, options, refs, cdefs)
|
219
|
-
end
|
220
|
-
|
221
|
-
val
|
222
|
-
when 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77
|
223
|
-
# 0x70 - 0x77 fixed list with direct length
|
224
|
-
parse_type(bytes)
|
225
|
-
|
226
|
-
is_struct, klass = read_klass(klass)
|
227
|
-
|
228
|
-
if is_struct
|
229
|
-
arr = []
|
230
|
-
(bc - BC_LIST_DIRECT).times do
|
231
|
-
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
232
|
-
end
|
233
|
-
|
234
|
-
val = klass.new(*arr)
|
235
|
-
refs << val
|
236
|
-
else
|
237
|
-
val = []
|
238
|
-
refs << val # store a value reference first
|
239
|
-
(bc - BC_LIST_DIRECT).times do
|
240
|
-
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
val
|
245
|
-
when 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
|
246
|
-
# 0x78 - 0x7f fixed untyped list with direct length
|
247
|
-
is_struct, klass = read_klass(klass)
|
248
|
-
|
249
|
-
if is_struct
|
250
|
-
arr = []
|
251
|
-
(bc - BC_LIST_DIRECT_UNTYPED).times do
|
252
|
-
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
253
|
-
end
|
254
|
-
|
255
|
-
val = klass.new(*arr)
|
256
|
-
refs << val
|
257
|
-
else
|
258
|
-
val = []
|
259
|
-
refs << val # store a value reference first
|
260
|
-
(bc - BC_LIST_DIRECT_UNTYPED).times do
|
261
|
-
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
val
|
266
|
-
when 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
267
|
-
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
268
|
-
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
269
|
-
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
270
|
-
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
271
|
-
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
272
|
-
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
273
|
-
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
|
274
|
-
# 0x80 - 0xbf one-octet compact int (-x10 to x2f, x90 is 0)
|
275
|
-
read_int_zero(bc)
|
276
|
-
when 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
277
|
-
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
278
|
-
# 0xc0 - 0xcf two-octet compact int (-x800 to x7ff)
|
279
|
-
read_int_byte_zero(bytes, bc)
|
280
|
-
when 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
|
281
|
-
# 0xd0 - 0xd7 three-octet compact int (-x40000 to x3ffff)
|
282
|
-
read_int_short_zero(bytes, bc)
|
283
|
-
when 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
284
|
-
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
285
|
-
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef
|
286
|
-
# 0xd8 - 0xef one-octet compact long (-x8 to xf, xe0 is 0)
|
287
|
-
read_long_zero(bc)
|
288
|
-
when 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
289
|
-
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
290
|
-
# 0xf0 - 0xff two-octet compact long (-x800 to x7ff, xf8 is 0)
|
291
|
-
read_long_byte_zero(bytes, bc)
|
292
|
-
else
|
293
|
-
raise sprintf("Invalid type: %#x", bc)
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
|
298
|
-
def parse_utf8_char(bytes)
|
299
|
-
bc = bytes.next
|
300
|
-
if bc < 0x80 # 0xxxxxxx
|
301
|
-
bc
|
302
|
-
elsif bc & 0xe0 == 0xc0 # 110xxxxx 10xxxxxx
|
303
|
-
(bc & 0x1f) * 64 + (bytes.next & 0x3f)
|
304
|
-
elsif bc & 0xf0 == 0xe0 # 1110xxxx 10xxxxxx 10xxxxxx
|
305
|
-
(bc & 0x0f) * 4096 + (bytes.next & 0x3f) * 64 + (bytes.next & 0x3f)
|
306
|
-
else
|
307
|
-
raise sprintf("bad utf-8 encoding at %#x", bc)
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
|
312
|
-
def parse_binary(bytes)
|
313
|
-
bc = bytes.next
|
314
|
-
case bc
|
315
|
-
when 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
316
|
-
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
317
|
-
read_binary_direct(bytes, bc)
|
318
|
-
when 0x34, 0x35, 0x36, 0x37
|
319
|
-
read_binary_short(bytes, bc)
|
320
|
-
when 0x41
|
321
|
-
read_binary_chunk(bytes)
|
322
|
-
when 0x42
|
323
|
-
read_binary(bytes)
|
324
|
-
else
|
325
|
-
raise sprintf("%#x is not a binary", bc)
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
|
330
|
-
def parse_int(bytes)
|
331
|
-
bc = bytes.next
|
332
|
-
case bc
|
333
|
-
when 0x49
|
334
|
-
read_int(bytes)
|
335
|
-
when 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
336
|
-
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
337
|
-
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
338
|
-
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
339
|
-
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
340
|
-
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
341
|
-
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
342
|
-
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
|
343
|
-
read_int_zero(bc)
|
344
|
-
when 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
345
|
-
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
346
|
-
read_int_byte_zero(bytes, bc)
|
347
|
-
when 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
|
348
|
-
read_int_short_zero(bytes, bc)
|
349
|
-
else
|
350
|
-
raise sprintf("%#x is not a int", bc)
|
351
|
-
end
|
352
|
-
end
|
353
|
-
|
354
|
-
|
355
|
-
def parse_string(bytes)
|
356
|
-
bc = bytes.next
|
357
|
-
case bc
|
358
|
-
when 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
359
|
-
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
360
|
-
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
361
|
-
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
362
|
-
read_string_direct(bytes, bc)
|
363
|
-
when 0x30, 0x31, 0x32, 0x33
|
364
|
-
read_string_short(bytes, bc)
|
365
|
-
when 0x52
|
366
|
-
read_string_chunk(bytes)
|
367
|
-
when 0x53
|
368
|
-
read_string(bytes)
|
369
|
-
else
|
370
|
-
raise sprintf("%#x is not a string", bc)
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
|
375
|
-
def parse_type(bytes)
|
376
|
-
bc = bytes.next
|
377
|
-
case bc
|
378
|
-
when 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
379
|
-
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
380
|
-
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
381
|
-
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
382
|
-
read_string_direct(bytes, bc)
|
383
|
-
when 0x30, 0x31, 0x32, 0x33
|
384
|
-
read_string_short(bytes, bc)
|
385
|
-
when 0x49
|
386
|
-
read_int(bytes)
|
387
|
-
when 0x52
|
388
|
-
read_string_chunk(bytes)
|
389
|
-
when 0x53
|
390
|
-
read_string(bytes)
|
391
|
-
when 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
392
|
-
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
393
|
-
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
394
|
-
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
395
|
-
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
396
|
-
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
397
|
-
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
398
|
-
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
|
399
|
-
read_int_zero(bc)
|
400
|
-
when 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
401
|
-
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
402
|
-
read_int_byte_zero(bytes, bc)
|
403
|
-
when 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
|
404
|
-
read_int_short_zero(bytes, bc)
|
405
|
-
else
|
406
|
-
raise sprintf("%#x is not a type", bc)
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
|
411
|
-
private
|
412
|
-
|
413
|
-
def read_binary_direct(bytes, bc)
|
414
|
-
read_binary_string(bytes, bc - BC_BINARY_DIRECT)
|
415
|
-
end
|
416
|
-
|
417
|
-
|
418
|
-
def read_binary_short(bytes, bc)
|
419
|
-
read_binary_string(bytes, ((bc - BC_BINARY_SHORT) << 8) + bytes.next)
|
420
|
-
end
|
421
|
-
|
422
|
-
|
423
|
-
def read_binary_chunk(bytes)
|
424
|
-
chunks = []
|
425
|
-
chunks << read_binary(bytes)
|
426
|
-
while(bytes.peek == BC_BINARY_CHUNK)
|
427
|
-
bytes.next
|
428
|
-
chunks << read_binary(bytes)
|
429
|
-
end
|
430
|
-
|
431
|
-
chunks << parse_binary(bytes)
|
432
|
-
chunks.join
|
433
|
-
end
|
434
|
-
|
435
|
-
|
436
|
-
def read_binary(bytes)
|
437
|
-
read_binary_string(bytes, bytes.next * 256 + bytes.next)
|
438
|
-
end
|
439
|
-
|
440
|
-
|
441
|
-
def read_binary_string(bytes, len)
|
442
|
-
[].tap do |arr|
|
443
|
-
len.times{ arr << bytes.next }
|
444
|
-
end.pack('C*')
|
445
|
-
end
|
446
|
-
|
447
|
-
|
448
|
-
def read_date(bytes)
|
449
|
-
val = read_long(bytes)
|
450
|
-
Time.at(val / 1000, val % 1000 * 1000)
|
451
|
-
end
|
452
|
-
|
453
|
-
|
454
|
-
def read_date_minute(bytes)
|
455
|
-
val = bytes.next * 16777216 + bytes.next * 65536 + bytes.next * 256 + bytes.next
|
456
|
-
Time.at(val * 60)
|
457
|
-
end
|
458
|
-
|
459
|
-
|
460
|
-
def read_double(bytes)
|
461
|
-
# b64, b56, b48, b40, b32, b24, b16, b8 = bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next
|
462
|
-
# bits = b64 * 72057594037927936 + b56 * 281474976710656 + b48 * 1099511627776 + b40 * 4294967296 \
|
463
|
-
# + b32 * 16777216 + b24 * 65536 + b16 * 256 + b8
|
464
|
-
# return Float::INFINITY if bits == 0x7_ff0_000_000_000_000
|
465
|
-
# return -Float::INFINITY if bits == 0xf_ff0_000_000_000_000
|
466
|
-
# return Float::NAN if (bits >= 0x7_ff0_000_000_000_001 && bits <= 0x7_fff_fff_fff_fff_fff) or (bits >= 0xf_ff0_000_000_000_001 && bits <= 0xf_fff_fff_fff_fff_fff)
|
467
|
-
# s = b64 < 0x80 ? 1 : -1
|
468
|
-
# e = (bits / 4503599627370496) & 0x7ff
|
469
|
-
# m = (e == 0) ? (bits & 0xf_fff_fff_fff_fff) << 1 : (bits & 0xf_fff_fff_fff_fff) | 0x10_000_000_000_000
|
470
|
-
# (s * m * 2**(e - 1075)).to_f # maybe get a rational, so to_f
|
471
|
-
[ bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next ].pack('C*').unpack('G').first # faster than s * m * 2**(e - 1075)
|
472
|
-
end
|
473
|
-
|
474
|
-
|
475
|
-
def read_double_direct(bytes)
|
476
|
-
bc = bytes.next
|
477
|
-
bc < 0x80 ? bc : -(0xff - bc + 1)
|
478
|
-
end
|
479
|
-
|
480
|
-
|
481
|
-
def read_double_short(bytes)
|
482
|
-
b16, b8 = bytes.next, bytes.next
|
483
|
-
if b16 < 0x80
|
484
|
-
b16 * 256 + b8
|
485
|
-
else
|
486
|
-
-((0xff - b16) * 256 + 0xff - b8 + 1)
|
487
|
-
end
|
488
|
-
end
|
489
|
-
|
490
|
-
|
491
|
-
def read_double_mill(bytes)
|
492
|
-
0.001 * read_int(bytes)
|
493
|
-
end
|
494
|
-
|
495
|
-
|
496
|
-
def read_hash(bytes, klass, options, refs, cdefs)
|
497
|
-
val = {}
|
498
|
-
refs << val
|
499
|
-
if options[:symbolize_keys]
|
500
|
-
val[parse_bytes(bytes, klass, options, refs, cdefs).to_sym] = parse_bytes(bytes, klass, options, refs, cdefs) while bytes.peek != BC_END
|
501
|
-
else
|
502
|
-
val[parse_bytes(bytes, klass, options, refs, cdefs)] = parse_bytes(bytes, klass, options, refs, cdefs) while bytes.peek != BC_END
|
503
|
-
end
|
504
|
-
bytes.next
|
505
|
-
|
506
|
-
val
|
507
|
-
end
|
508
|
-
|
509
|
-
|
510
|
-
def read_int(bytes)
|
511
|
-
b32, b24, b16, b8 = bytes.next, bytes.next, bytes.next, bytes.next
|
512
|
-
if b32 < 0x80
|
513
|
-
b32 * 16777216 + b24 * 65536 + b16 * 256 + b8
|
514
|
-
else
|
515
|
-
-((0xff - b32) * 16777216 + (0xff - b24) * 65536 + (0xff - b16) * 256 + 0xff - b8 + 1)
|
516
|
-
end
|
517
|
-
end
|
518
|
-
|
519
|
-
|
520
|
-
def read_int_zero(bc)
|
521
|
-
bc - BC_INT_ZERO
|
522
|
-
end
|
523
|
-
|
524
|
-
|
525
|
-
def read_int_byte_zero(bytes, bc)
|
526
|
-
(bc - BC_INT_BYTE_ZERO) * 256 + bytes.next
|
527
|
-
end
|
528
|
-
|
529
|
-
|
530
|
-
def read_int_short_zero(bytes, bc)
|
531
|
-
(bc - BC_INT_SHORT_ZERO) * 65536 + bytes.next * 256 + bytes.next
|
532
|
-
end
|
533
|
-
|
534
|
-
|
535
|
-
def read_klass(klass)
|
536
|
-
if klass.nil?
|
537
|
-
is_struct = false
|
538
|
-
elsif klass.is_a?(Array)
|
539
|
-
is_struct = false
|
540
|
-
klass = klass.first
|
541
|
-
elsif klass.is_a?(String)
|
542
|
-
if klass.include?('[')
|
543
|
-
is_struct = false
|
544
|
-
klass = Kernel.const_get(klass.delete('[]'))
|
545
|
-
else
|
546
|
-
is_struct = true
|
547
|
-
klass = Kernel.const_get(klass)
|
548
|
-
end
|
549
|
-
else
|
550
|
-
is_struct = true
|
551
|
-
end
|
552
|
-
|
553
|
-
[ is_struct, klass ]
|
554
|
-
end
|
555
|
-
|
556
|
-
|
557
|
-
def read_long(bytes)
|
558
|
-
b64, b56, b48, b40, b32, b24, b16, b8 = bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next
|
559
|
-
if b64 < 0x80
|
560
|
-
b64 * 72057594037927936 + b56 * 281474976710656 + b48 * 1099511627776 + b40 * 4294967296 \
|
561
|
-
+ b32 * 16777216 + b24 * 65536 + b16 * 256 + b8
|
562
|
-
else
|
563
|
-
-((0xff - b64) * 72057594037927936 + (0xff - b56) * 281474976710656 + (0xff - b48) * 1099511627776 + (0xff - b40) * 4294967296 \
|
564
|
-
+ (0xff - b32) * 16777216 + (0xff - b24) * 65536 + (0xff - b16) * 256 + 0xff - b8 + 1)
|
565
|
-
end
|
566
|
-
end
|
567
|
-
|
568
|
-
|
569
|
-
def read_long_zero(bc)
|
570
|
-
bc - BC_LONG_ZERO
|
571
|
-
end
|
572
|
-
|
573
|
-
|
574
|
-
def read_long_byte_zero(bytes, bc)
|
575
|
-
(bc - BC_LONG_BYTE_ZERO) * 256 + bytes.next
|
576
|
-
end
|
577
|
-
|
578
|
-
|
579
|
-
def read_long_short_zero(bytes, bc)
|
580
|
-
(bc - BC_LONG_SHORT_ZERO) * 65536 + bytes.next * 256 + bytes.next
|
581
|
-
end
|
582
|
-
|
583
|
-
|
584
|
-
def read_string_direct(bytes, bc)
|
585
|
-
read_utf8_string(bytes, bc - BC_STRING_DIRECT)
|
586
|
-
end
|
587
|
-
|
588
|
-
|
589
|
-
def read_string_short(bytes, bc)
|
590
|
-
read_utf8_string(bytes, (bc - BC_STRING_SHORT) * 256 + bytes.next)
|
591
|
-
end
|
592
|
-
|
593
|
-
|
594
|
-
def read_string_chunk(bytes)
|
595
|
-
chunks = []
|
596
|
-
chunks << read_string(bytes)
|
597
|
-
while(bytes.peek == BC_STRING_CHUNK)
|
598
|
-
bytes.next
|
599
|
-
chunks << read_string(bytes)
|
600
|
-
end
|
601
|
-
|
602
|
-
chunks << parse_string(bytes)
|
603
|
-
chunks.join
|
604
|
-
end
|
605
|
-
|
606
|
-
|
607
|
-
def read_string(bytes)
|
608
|
-
read_utf8_string(bytes, bytes.next * 256 + bytes.next)
|
609
|
-
end
|
610
|
-
|
611
|
-
|
612
|
-
def read_utf8_string(bytes, len)
|
613
|
-
[].tap do |chars|
|
614
|
-
len.times{ chars << parse_utf8_char(bytes) }
|
615
|
-
end.pack('U*')
|
616
|
-
end
|
617
|
-
|
618
|
-
end
|
619
|
-
end
|
1
|
+
require 'hessian2/constants'
|
2
|
+
require 'hessian2/fault'
|
3
|
+
|
4
|
+
module Hessian2
|
5
|
+
module Parser
|
6
|
+
include Constants
|
7
|
+
|
8
|
+
def parse_rpc(data)
|
9
|
+
bytes = data.each_byte
|
10
|
+
bc = bytes.next
|
11
|
+
if bc == 0x48 # skip hessian version
|
12
|
+
2.times{ bytes.next }
|
13
|
+
bc = bytes.next
|
14
|
+
end
|
15
|
+
|
16
|
+
case bc
|
17
|
+
when 0x43 # rpc call ('C')
|
18
|
+
method = parse_string(bytes)
|
19
|
+
refs, cdefs = [], []
|
20
|
+
args = [].tap do |arr|
|
21
|
+
parse_int(bytes).times{ arr << parse_bytes(bytes, nil, {}, refs, cdefs) }
|
22
|
+
end
|
23
|
+
[ method, *args ]
|
24
|
+
when 0x46 # fault ('F')
|
25
|
+
fault = parse_bytes(bytes)
|
26
|
+
code, message = fault['code'], fault['message']
|
27
|
+
raise Fault.new, code == 'RuntimeError' ? message : "#{code} - #{message}"
|
28
|
+
when 0x52 # rpc result ('R')
|
29
|
+
parse_bytes(bytes)
|
30
|
+
else
|
31
|
+
raise data
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def parse(data, klass = nil, options = {})
|
37
|
+
parse_bytes(data.each_byte, klass, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def parse_bytes(bytes, klass = nil, options = {}, refs = [], cdefs = [])
|
42
|
+
bc = bytes.next
|
43
|
+
case bc
|
44
|
+
when 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
45
|
+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
46
|
+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
47
|
+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
48
|
+
# 0x00 - 0x1f utf-8 string length 0-31
|
49
|
+
read_string_direct(bytes, bc)
|
50
|
+
when 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
51
|
+
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
52
|
+
# 0x20 - 0x2f binary data length 0-15
|
53
|
+
read_binary_direct(bytes, bc)
|
54
|
+
when 0x30, 0x31, 0x32, 0x33
|
55
|
+
# 0x30 - 0x33 utf-8 string length 0-1023
|
56
|
+
read_string_short(bytes, bc)
|
57
|
+
when 0x34, 0x35, 0x36, 0x37
|
58
|
+
# 0x34 - 0x37 binary data length 0-1023
|
59
|
+
read_binary_short(bytes, bc)
|
60
|
+
when 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
|
61
|
+
# 0x38 - 0x3f three-octet compact long (-x40000 to x3ffff)
|
62
|
+
read_long_short_zero(bytes, bc)
|
63
|
+
when 0x41 # 8-bit binary data non-final chunk ('A')
|
64
|
+
read_binary_chunk(bytes)
|
65
|
+
when 0x42 # 8-bit binary data final chunk ('B')
|
66
|
+
read_binary(bytes)
|
67
|
+
when 0x43 # object type definition ('C')
|
68
|
+
name = parse_string(bytes)
|
69
|
+
fields = []
|
70
|
+
|
71
|
+
parse_int(bytes).times do
|
72
|
+
fields << parse_string(bytes)
|
73
|
+
end
|
74
|
+
cdefs << Struct.new(*fields.map{|f| f.to_sym})
|
75
|
+
|
76
|
+
parse_bytes(bytes, klass, options, refs, cdefs)
|
77
|
+
when 0x44 # 64-bit IEEE encoded double ('D')
|
78
|
+
read_double(bytes)
|
79
|
+
when 0x46 # boolean false ('F')
|
80
|
+
false
|
81
|
+
when 0x48 # untyped map ('H')
|
82
|
+
read_hash(bytes, klass, options, refs, cdefs)
|
83
|
+
when 0x49 # 32-bit signed integer ('I')
|
84
|
+
read_int(bytes)
|
85
|
+
when 0x4a # 64-bit UTC millisecond date
|
86
|
+
read_date(bytes)
|
87
|
+
when 0x4b # 32-bit UTC minute date
|
88
|
+
read_date_minute(bytes)
|
89
|
+
when 0x4c # 64-bit signed long integer ('L')
|
90
|
+
read_long(bytes)
|
91
|
+
when 0x4d # map with type ('M')
|
92
|
+
parse_type(bytes)
|
93
|
+
read_hash(bytes, klass, options, refs, cdefs)
|
94
|
+
when 0x4e # null ('N')
|
95
|
+
nil
|
96
|
+
when 0x4f # object instance ('O')
|
97
|
+
cdef = cdefs[parse_int(bytes)]
|
98
|
+
val = cdef.new
|
99
|
+
refs << val # store a value reference first
|
100
|
+
val.members.each do |sym|
|
101
|
+
val[sym] = parse_bytes(bytes, klass, options, refs, cdefs)
|
102
|
+
end
|
103
|
+
|
104
|
+
val
|
105
|
+
when 0x51 # reference to map/list/object - integer ('Q')
|
106
|
+
refs[parse_int(bytes)]
|
107
|
+
when 0x52 # utf-8 string non-final chunk ('R')
|
108
|
+
read_string_chunk(bytes)
|
109
|
+
when 0x53 # utf-8 string final chunk ('S')
|
110
|
+
read_string(bytes)
|
111
|
+
when 0x54 # boolean true ('T')
|
112
|
+
true
|
113
|
+
when 0x55 # variable-length list/vector ('U')
|
114
|
+
parse_type(bytes)
|
115
|
+
|
116
|
+
is_struct, klass = read_klass(klass)
|
117
|
+
|
118
|
+
if is_struct
|
119
|
+
arr = []
|
120
|
+
while bytes.peek != BC_END
|
121
|
+
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
122
|
+
end
|
123
|
+
|
124
|
+
val = klass.new(*arr)
|
125
|
+
refs << val
|
126
|
+
else
|
127
|
+
val = []
|
128
|
+
refs << val # store a value reference first
|
129
|
+
while bytes.peek != BC_END
|
130
|
+
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
bytes.next
|
135
|
+
val
|
136
|
+
when 0x56 # fixed-length list/vector ('V')
|
137
|
+
parse_type(bytes)
|
138
|
+
|
139
|
+
is_struct, klass = read_klass(klass)
|
140
|
+
|
141
|
+
if is_struct
|
142
|
+
arr = []
|
143
|
+
parse_int(bytes).times do
|
144
|
+
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
145
|
+
end
|
146
|
+
|
147
|
+
val = klass.new(*arr)
|
148
|
+
refs << val
|
149
|
+
else
|
150
|
+
val = []
|
151
|
+
refs << val # store a value reference
|
152
|
+
parse_int(bytes).times do
|
153
|
+
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
val
|
158
|
+
when 0x57 # variable-length untyped list/vector ('W')
|
159
|
+
is_struct, klass = read_klass(klass)
|
160
|
+
|
161
|
+
if is_struct
|
162
|
+
arr = []
|
163
|
+
while bytes.peek != BC_END
|
164
|
+
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
165
|
+
end
|
166
|
+
|
167
|
+
val = klass.new(*arr)
|
168
|
+
refs << val
|
169
|
+
else
|
170
|
+
val = []
|
171
|
+
refs << val # store a value reference first
|
172
|
+
while bytes.peek != BC_END
|
173
|
+
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
bytes.next
|
178
|
+
val
|
179
|
+
when 0x58 # fixed-length untyped list/vector ('X')
|
180
|
+
is_struct, klass = read_klass(klass)
|
181
|
+
|
182
|
+
if is_struct
|
183
|
+
arr = []
|
184
|
+
parse_int(bytes).times do
|
185
|
+
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
186
|
+
end
|
187
|
+
|
188
|
+
val = klass.new(*arr)
|
189
|
+
refs << val
|
190
|
+
else
|
191
|
+
val = []
|
192
|
+
refs << val # store a value reference first
|
193
|
+
parse_int(bytes).times do
|
194
|
+
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
val
|
199
|
+
when 0x59 # long encoded as 32-bit int ('Y')
|
200
|
+
read_int(bytes)
|
201
|
+
when 0x5b # double 0.0
|
202
|
+
0
|
203
|
+
when 0x5c # double 1.0
|
204
|
+
1
|
205
|
+
when 0x5d # double represented as byte (-128.0 to 127.0)
|
206
|
+
read_double_direct(bytes)
|
207
|
+
when 0x5e # double represented as short (-32768.0 to 32767.0)
|
208
|
+
read_double_short(bytes)
|
209
|
+
when 0x5f # double represented as float
|
210
|
+
read_double_mill(bytes)
|
211
|
+
when 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
212
|
+
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f
|
213
|
+
# 0x60 - 0x6f object with direct type
|
214
|
+
cdef = cdefs[bc - BC_OBJECT_DIRECT]
|
215
|
+
val = cdef.new
|
216
|
+
refs << val # store a value reference first
|
217
|
+
val.members.each do |sym|
|
218
|
+
val[sym] = parse_bytes(bytes, klass, options, refs, cdefs)
|
219
|
+
end
|
220
|
+
|
221
|
+
val
|
222
|
+
when 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77
|
223
|
+
# 0x70 - 0x77 fixed list with direct length
|
224
|
+
parse_type(bytes)
|
225
|
+
|
226
|
+
is_struct, klass = read_klass(klass)
|
227
|
+
|
228
|
+
if is_struct
|
229
|
+
arr = []
|
230
|
+
(bc - BC_LIST_DIRECT).times do
|
231
|
+
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
232
|
+
end
|
233
|
+
|
234
|
+
val = klass.new(*arr)
|
235
|
+
refs << val
|
236
|
+
else
|
237
|
+
val = []
|
238
|
+
refs << val # store a value reference first
|
239
|
+
(bc - BC_LIST_DIRECT).times do
|
240
|
+
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
val
|
245
|
+
when 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
|
246
|
+
# 0x78 - 0x7f fixed untyped list with direct length
|
247
|
+
is_struct, klass = read_klass(klass)
|
248
|
+
|
249
|
+
if is_struct
|
250
|
+
arr = []
|
251
|
+
(bc - BC_LIST_DIRECT_UNTYPED).times do
|
252
|
+
arr << parse_bytes(bytes, nil, options, refs, cdefs)
|
253
|
+
end
|
254
|
+
|
255
|
+
val = klass.new(*arr)
|
256
|
+
refs << val
|
257
|
+
else
|
258
|
+
val = []
|
259
|
+
refs << val # store a value reference first
|
260
|
+
(bc - BC_LIST_DIRECT_UNTYPED).times do
|
261
|
+
val << parse_bytes(bytes, klass, options, refs, cdefs)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
val
|
266
|
+
when 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
267
|
+
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
268
|
+
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
269
|
+
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
270
|
+
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
271
|
+
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
272
|
+
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
273
|
+
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
|
274
|
+
# 0x80 - 0xbf one-octet compact int (-x10 to x2f, x90 is 0)
|
275
|
+
read_int_zero(bc)
|
276
|
+
when 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
277
|
+
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
278
|
+
# 0xc0 - 0xcf two-octet compact int (-x800 to x7ff)
|
279
|
+
read_int_byte_zero(bytes, bc)
|
280
|
+
when 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
|
281
|
+
# 0xd0 - 0xd7 three-octet compact int (-x40000 to x3ffff)
|
282
|
+
read_int_short_zero(bytes, bc)
|
283
|
+
when 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
284
|
+
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
285
|
+
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef
|
286
|
+
# 0xd8 - 0xef one-octet compact long (-x8 to xf, xe0 is 0)
|
287
|
+
read_long_zero(bc)
|
288
|
+
when 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
289
|
+
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
290
|
+
# 0xf0 - 0xff two-octet compact long (-x800 to x7ff, xf8 is 0)
|
291
|
+
read_long_byte_zero(bytes, bc)
|
292
|
+
else
|
293
|
+
raise sprintf("Invalid type: %#x", bc)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
def parse_utf8_char(bytes)
|
299
|
+
bc = bytes.next
|
300
|
+
if bc < 0x80 # 0xxxxxxx
|
301
|
+
bc
|
302
|
+
elsif bc & 0xe0 == 0xc0 # 110xxxxx 10xxxxxx
|
303
|
+
(bc & 0x1f) * 64 + (bytes.next & 0x3f)
|
304
|
+
elsif bc & 0xf0 == 0xe0 # 1110xxxx 10xxxxxx 10xxxxxx
|
305
|
+
(bc & 0x0f) * 4096 + (bytes.next & 0x3f) * 64 + (bytes.next & 0x3f)
|
306
|
+
else
|
307
|
+
raise sprintf("bad utf-8 encoding at %#x", bc)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
|
312
|
+
def parse_binary(bytes)
|
313
|
+
bc = bytes.next
|
314
|
+
case bc
|
315
|
+
when 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
316
|
+
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
317
|
+
read_binary_direct(bytes, bc)
|
318
|
+
when 0x34, 0x35, 0x36, 0x37
|
319
|
+
read_binary_short(bytes, bc)
|
320
|
+
when 0x41
|
321
|
+
read_binary_chunk(bytes)
|
322
|
+
when 0x42
|
323
|
+
read_binary(bytes)
|
324
|
+
else
|
325
|
+
raise sprintf("%#x is not a binary", bc)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
def parse_int(bytes)
|
331
|
+
bc = bytes.next
|
332
|
+
case bc
|
333
|
+
when 0x49
|
334
|
+
read_int(bytes)
|
335
|
+
when 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
336
|
+
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
337
|
+
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
338
|
+
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
339
|
+
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
340
|
+
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
341
|
+
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
342
|
+
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
|
343
|
+
read_int_zero(bc)
|
344
|
+
when 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
345
|
+
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
346
|
+
read_int_byte_zero(bytes, bc)
|
347
|
+
when 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
|
348
|
+
read_int_short_zero(bytes, bc)
|
349
|
+
else
|
350
|
+
raise sprintf("%#x is not a int", bc)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
def parse_string(bytes)
|
356
|
+
bc = bytes.next
|
357
|
+
case bc
|
358
|
+
when 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
359
|
+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
360
|
+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
361
|
+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
362
|
+
read_string_direct(bytes, bc)
|
363
|
+
when 0x30, 0x31, 0x32, 0x33
|
364
|
+
read_string_short(bytes, bc)
|
365
|
+
when 0x52
|
366
|
+
read_string_chunk(bytes)
|
367
|
+
when 0x53
|
368
|
+
read_string(bytes)
|
369
|
+
else
|
370
|
+
raise sprintf("%#x is not a string", bc)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
|
375
|
+
def parse_type(bytes)
|
376
|
+
bc = bytes.next
|
377
|
+
case bc
|
378
|
+
when 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
379
|
+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
380
|
+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
381
|
+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
382
|
+
read_string_direct(bytes, bc)
|
383
|
+
when 0x30, 0x31, 0x32, 0x33
|
384
|
+
read_string_short(bytes, bc)
|
385
|
+
when 0x49
|
386
|
+
read_int(bytes)
|
387
|
+
when 0x52
|
388
|
+
read_string_chunk(bytes)
|
389
|
+
when 0x53
|
390
|
+
read_string(bytes)
|
391
|
+
when 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
392
|
+
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
393
|
+
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
394
|
+
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
395
|
+
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
396
|
+
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
397
|
+
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
398
|
+
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
|
399
|
+
read_int_zero(bc)
|
400
|
+
when 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
401
|
+
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
|
402
|
+
read_int_byte_zero(bytes, bc)
|
403
|
+
when 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
|
404
|
+
read_int_short_zero(bytes, bc)
|
405
|
+
else
|
406
|
+
raise sprintf("%#x is not a type", bc)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
|
411
|
+
private
|
412
|
+
|
413
|
+
def read_binary_direct(bytes, bc)
|
414
|
+
read_binary_string(bytes, bc - BC_BINARY_DIRECT)
|
415
|
+
end
|
416
|
+
|
417
|
+
|
418
|
+
def read_binary_short(bytes, bc)
|
419
|
+
read_binary_string(bytes, ((bc - BC_BINARY_SHORT) << 8) + bytes.next)
|
420
|
+
end
|
421
|
+
|
422
|
+
|
423
|
+
def read_binary_chunk(bytes)
|
424
|
+
chunks = []
|
425
|
+
chunks << read_binary(bytes)
|
426
|
+
while(bytes.peek == BC_BINARY_CHUNK)
|
427
|
+
bytes.next
|
428
|
+
chunks << read_binary(bytes)
|
429
|
+
end
|
430
|
+
|
431
|
+
chunks << parse_binary(bytes)
|
432
|
+
chunks.join
|
433
|
+
end
|
434
|
+
|
435
|
+
|
436
|
+
def read_binary(bytes)
|
437
|
+
read_binary_string(bytes, bytes.next * 256 + bytes.next)
|
438
|
+
end
|
439
|
+
|
440
|
+
|
441
|
+
def read_binary_string(bytes, len)
|
442
|
+
[].tap do |arr|
|
443
|
+
len.times{ arr << bytes.next }
|
444
|
+
end.pack('C*')
|
445
|
+
end
|
446
|
+
|
447
|
+
|
448
|
+
def read_date(bytes)
|
449
|
+
val = read_long(bytes)
|
450
|
+
Time.at(val / 1000, val % 1000 * 1000)
|
451
|
+
end
|
452
|
+
|
453
|
+
|
454
|
+
def read_date_minute(bytes)
|
455
|
+
val = bytes.next * 16777216 + bytes.next * 65536 + bytes.next * 256 + bytes.next
|
456
|
+
Time.at(val * 60)
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
def read_double(bytes)
|
461
|
+
# b64, b56, b48, b40, b32, b24, b16, b8 = bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next
|
462
|
+
# bits = b64 * 72057594037927936 + b56 * 281474976710656 + b48 * 1099511627776 + b40 * 4294967296 \
|
463
|
+
# + b32 * 16777216 + b24 * 65536 + b16 * 256 + b8
|
464
|
+
# return Float::INFINITY if bits == 0x7_ff0_000_000_000_000
|
465
|
+
# return -Float::INFINITY if bits == 0xf_ff0_000_000_000_000
|
466
|
+
# return Float::NAN if (bits >= 0x7_ff0_000_000_000_001 && bits <= 0x7_fff_fff_fff_fff_fff) or (bits >= 0xf_ff0_000_000_000_001 && bits <= 0xf_fff_fff_fff_fff_fff)
|
467
|
+
# s = b64 < 0x80 ? 1 : -1
|
468
|
+
# e = (bits / 4503599627370496) & 0x7ff
|
469
|
+
# m = (e == 0) ? (bits & 0xf_fff_fff_fff_fff) << 1 : (bits & 0xf_fff_fff_fff_fff) | 0x10_000_000_000_000
|
470
|
+
# (s * m * 2**(e - 1075)).to_f # maybe get a rational, so to_f
|
471
|
+
[ bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next ].pack('C*').unpack('G').first # faster than s * m * 2**(e - 1075)
|
472
|
+
end
|
473
|
+
|
474
|
+
|
475
|
+
def read_double_direct(bytes)
|
476
|
+
bc = bytes.next
|
477
|
+
bc < 0x80 ? bc : -(0xff - bc + 1)
|
478
|
+
end
|
479
|
+
|
480
|
+
|
481
|
+
def read_double_short(bytes)
|
482
|
+
b16, b8 = bytes.next, bytes.next
|
483
|
+
if b16 < 0x80
|
484
|
+
b16 * 256 + b8
|
485
|
+
else
|
486
|
+
-((0xff - b16) * 256 + 0xff - b8 + 1)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
|
491
|
+
def read_double_mill(bytes)
|
492
|
+
0.001 * read_int(bytes)
|
493
|
+
end
|
494
|
+
|
495
|
+
|
496
|
+
def read_hash(bytes, klass, options, refs, cdefs)
|
497
|
+
val = {}
|
498
|
+
refs << val
|
499
|
+
if options[:symbolize_keys]
|
500
|
+
val[parse_bytes(bytes, klass, options, refs, cdefs).to_sym] = parse_bytes(bytes, klass, options, refs, cdefs) while bytes.peek != BC_END
|
501
|
+
else
|
502
|
+
val[parse_bytes(bytes, klass, options, refs, cdefs)] = parse_bytes(bytes, klass, options, refs, cdefs) while bytes.peek != BC_END
|
503
|
+
end
|
504
|
+
bytes.next
|
505
|
+
|
506
|
+
val
|
507
|
+
end
|
508
|
+
|
509
|
+
|
510
|
+
def read_int(bytes)
|
511
|
+
b32, b24, b16, b8 = bytes.next, bytes.next, bytes.next, bytes.next
|
512
|
+
if b32 < 0x80
|
513
|
+
b32 * 16777216 + b24 * 65536 + b16 * 256 + b8
|
514
|
+
else
|
515
|
+
-((0xff - b32) * 16777216 + (0xff - b24) * 65536 + (0xff - b16) * 256 + 0xff - b8 + 1)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
|
520
|
+
def read_int_zero(bc)
|
521
|
+
bc - BC_INT_ZERO
|
522
|
+
end
|
523
|
+
|
524
|
+
|
525
|
+
def read_int_byte_zero(bytes, bc)
|
526
|
+
(bc - BC_INT_BYTE_ZERO) * 256 + bytes.next
|
527
|
+
end
|
528
|
+
|
529
|
+
|
530
|
+
def read_int_short_zero(bytes, bc)
|
531
|
+
(bc - BC_INT_SHORT_ZERO) * 65536 + bytes.next * 256 + bytes.next
|
532
|
+
end
|
533
|
+
|
534
|
+
|
535
|
+
def read_klass(klass)
|
536
|
+
if klass.nil?
|
537
|
+
is_struct = false
|
538
|
+
elsif klass.is_a?(Array)
|
539
|
+
is_struct = false
|
540
|
+
klass = klass.first
|
541
|
+
elsif klass.is_a?(String)
|
542
|
+
if klass.include?('[')
|
543
|
+
is_struct = false
|
544
|
+
klass = Kernel.const_get(klass.delete('[]'))
|
545
|
+
else
|
546
|
+
is_struct = true
|
547
|
+
klass = Kernel.const_get(klass)
|
548
|
+
end
|
549
|
+
else
|
550
|
+
is_struct = true
|
551
|
+
end
|
552
|
+
|
553
|
+
[ is_struct, klass ]
|
554
|
+
end
|
555
|
+
|
556
|
+
|
557
|
+
def read_long(bytes)
|
558
|
+
b64, b56, b48, b40, b32, b24, b16, b8 = bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next, bytes.next
|
559
|
+
if b64 < 0x80
|
560
|
+
b64 * 72057594037927936 + b56 * 281474976710656 + b48 * 1099511627776 + b40 * 4294967296 \
|
561
|
+
+ b32 * 16777216 + b24 * 65536 + b16 * 256 + b8
|
562
|
+
else
|
563
|
+
-((0xff - b64) * 72057594037927936 + (0xff - b56) * 281474976710656 + (0xff - b48) * 1099511627776 + (0xff - b40) * 4294967296 \
|
564
|
+
+ (0xff - b32) * 16777216 + (0xff - b24) * 65536 + (0xff - b16) * 256 + 0xff - b8 + 1)
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
|
569
|
+
def read_long_zero(bc)
|
570
|
+
bc - BC_LONG_ZERO
|
571
|
+
end
|
572
|
+
|
573
|
+
|
574
|
+
def read_long_byte_zero(bytes, bc)
|
575
|
+
(bc - BC_LONG_BYTE_ZERO) * 256 + bytes.next
|
576
|
+
end
|
577
|
+
|
578
|
+
|
579
|
+
def read_long_short_zero(bytes, bc)
|
580
|
+
(bc - BC_LONG_SHORT_ZERO) * 65536 + bytes.next * 256 + bytes.next
|
581
|
+
end
|
582
|
+
|
583
|
+
|
584
|
+
def read_string_direct(bytes, bc)
|
585
|
+
read_utf8_string(bytes, bc - BC_STRING_DIRECT)
|
586
|
+
end
|
587
|
+
|
588
|
+
|
589
|
+
def read_string_short(bytes, bc)
|
590
|
+
read_utf8_string(bytes, (bc - BC_STRING_SHORT) * 256 + bytes.next)
|
591
|
+
end
|
592
|
+
|
593
|
+
|
594
|
+
def read_string_chunk(bytes)
|
595
|
+
chunks = []
|
596
|
+
chunks << read_string(bytes)
|
597
|
+
while(bytes.peek == BC_STRING_CHUNK)
|
598
|
+
bytes.next
|
599
|
+
chunks << read_string(bytes)
|
600
|
+
end
|
601
|
+
|
602
|
+
chunks << parse_string(bytes)
|
603
|
+
chunks.join
|
604
|
+
end
|
605
|
+
|
606
|
+
|
607
|
+
def read_string(bytes)
|
608
|
+
read_utf8_string(bytes, bytes.next * 256 + bytes.next)
|
609
|
+
end
|
610
|
+
|
611
|
+
|
612
|
+
def read_utf8_string(bytes, len)
|
613
|
+
[].tap do |chars|
|
614
|
+
len.times{ chars << parse_utf8_char(bytes) }
|
615
|
+
end.pack('U*')
|
616
|
+
end
|
617
|
+
|
618
|
+
end
|
619
|
+
end
|