hessian2 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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