hessian2 2.0.2 → 2.0.3

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -10
  3. data/README.md +197 -197
  4. data/hessian2.gemspec +0 -2
  5. data/lib/hessian2/client.rb +57 -50
  6. data/lib/hessian2/constants.rb +164 -164
  7. data/lib/hessian2/fault.rb +3 -3
  8. data/lib/hessian2/handler.rb +18 -18
  9. data/lib/hessian2/hessian_client.rb +3 -3
  10. data/lib/hessian2/parser.rb +619 -619
  11. data/lib/hessian2/type_wrapper.rb +49 -49
  12. data/lib/hessian2/version.rb +3 -3
  13. data/lib/hessian2/writer.rb +499 -499
  14. data/lib/hessian2.rb +14 -14
  15. data/spec/binary_spec.rb +51 -51
  16. data/spec/boolean_spec.rb +26 -26
  17. data/spec/class_wrapper_spec.rb +52 -52
  18. data/spec/create_monkeys.rb +14 -14
  19. data/spec/date_spec.rb +45 -45
  20. data/spec/double_spec.rb +78 -78
  21. data/spec/int_spec.rb +54 -54
  22. data/spec/list_spec.rb +66 -66
  23. data/spec/long_spec.rb +68 -68
  24. data/spec/map_spec.rb +36 -36
  25. data/spec/null_spec.rb +17 -17
  26. data/spec/object_spec.rb +78 -78
  27. data/spec/ref_spec.rb +43 -43
  28. data/spec/spec_helper.rb +23 -23
  29. data/spec/string_spec.rb +61 -61
  30. data/spec/struct_wrapper_spec.rb +47 -47
  31. data/spec/type_wrapper_spec.rb +102 -102
  32. data/test/app.rb +24 -24
  33. data/test/async/em_http_asleep.rb +25 -25
  34. data/test/async/em_http_sleep.rb +25 -25
  35. data/test/async/monkey.asleep.rb +27 -27
  36. data/test/async/mysql2_aquery.rb +37 -37
  37. data/test/fault/monkey.undefined_method.rb +5 -5
  38. data/test/fault/monkey.wrong_arguments.rb +5 -5
  39. data/test/fiber_concurrency/em_http_asleep.rb +17 -17
  40. data/test/fiber_concurrency/em_http_sleep.rb +17 -17
  41. data/test/fiber_concurrency/monkey.asleep.fiber_aware.rb +18 -18
  42. data/test/fiber_concurrency/mysql2_query.rb +29 -29
  43. data/test/fiber_concurrency/net_http_asleep.rb +19 -19
  44. data/test/fiber_concurrency/net_http_sleep.rb +19 -19
  45. data/test/fibered_rainbows/Gemfile +15 -15
  46. data/test/fibered_rainbows/config.ru +11 -11
  47. data/test/fibered_rainbows/rainbows.rb +13 -13
  48. data/test/monkey_service.rb +16 -16
  49. data/test/prepare.rb +7 -7
  50. data/test/thread_concurrency/active_record_execute.rb +29 -29
  51. data/test/thread_concurrency/monkey.asleep.rb +22 -22
  52. data/test/thread_concurrency/net_http_asleep.rb +24 -24
  53. data/test/thread_concurrency/net_http_sleep.rb +24 -24
  54. data/test/threaded_rainbows/Gemfile +13 -13
  55. data/test/threaded_rainbows/config.ru +9 -9
  56. data/test/threaded_rainbows/rainbows.rb +13 -13
  57. metadata +4 -74
@@ -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