msgpack-ably 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +26 -0
  4. data/ChangeLog +101 -0
  5. data/README.rdoc +129 -0
  6. data/Rakefile +110 -0
  7. data/doclib/msgpack.rb +77 -0
  8. data/doclib/msgpack/buffer.rb +193 -0
  9. data/doclib/msgpack/core_ext.rb +101 -0
  10. data/doclib/msgpack/error.rb +14 -0
  11. data/doclib/msgpack/packer.rb +134 -0
  12. data/doclib/msgpack/unpacker.rb +146 -0
  13. data/ext/msgpack/buffer.c +678 -0
  14. data/ext/msgpack/buffer.h +441 -0
  15. data/ext/msgpack/buffer_class.c +507 -0
  16. data/ext/msgpack/buffer_class.h +32 -0
  17. data/ext/msgpack/compat.h +113 -0
  18. data/ext/msgpack/core_ext.c +129 -0
  19. data/ext/msgpack/core_ext.h +26 -0
  20. data/ext/msgpack/extconf.rb +28 -0
  21. data/ext/msgpack/packer.c +168 -0
  22. data/ext/msgpack/packer.h +429 -0
  23. data/ext/msgpack/packer_class.c +302 -0
  24. data/ext/msgpack/packer_class.h +30 -0
  25. data/ext/msgpack/rbinit.c +33 -0
  26. data/ext/msgpack/rmem.c +94 -0
  27. data/ext/msgpack/rmem.h +109 -0
  28. data/ext/msgpack/sysdep.h +115 -0
  29. data/ext/msgpack/sysdep_endian.h +50 -0
  30. data/ext/msgpack/sysdep_types.h +46 -0
  31. data/ext/msgpack/unpacker.c +781 -0
  32. data/ext/msgpack/unpacker.h +122 -0
  33. data/ext/msgpack/unpacker_class.c +405 -0
  34. data/ext/msgpack/unpacker_class.h +32 -0
  35. data/lib/msgpack.rb +6 -0
  36. data/lib/msgpack/version.rb +3 -0
  37. data/msgpack.gemspec +26 -0
  38. data/msgpack.org.md +49 -0
  39. data/spec/cases.json +1 -0
  40. data/spec/cases.msg +0 -0
  41. data/spec/cases_compact.msg +0 -0
  42. data/spec/cases_spec.rb +39 -0
  43. data/spec/cruby/buffer_io_spec.rb +256 -0
  44. data/spec/cruby/buffer_packer.rb +29 -0
  45. data/spec/cruby/buffer_spec.rb +572 -0
  46. data/spec/cruby/buffer_unpacker.rb +19 -0
  47. data/spec/format_spec.rb +256 -0
  48. data/spec/packer_spec.rb +120 -0
  49. data/spec/random_compat.rb +24 -0
  50. data/spec/spec_helper.rb +21 -0
  51. data/spec/unpacker_spec.rb +305 -0
  52. metadata +195 -0
@@ -0,0 +1,122 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ #ifndef MSGPACK_RUBY_UNPACKER_H__
19
+ #define MSGPACK_RUBY_UNPACKER_H__
20
+
21
+ #include "buffer.h"
22
+
23
+ #ifndef MSGPACK_UNPACKER_STACK_CAPACITY
24
+ #define MSGPACK_UNPACKER_STACK_CAPACITY 128
25
+ #endif
26
+
27
+ struct msgpack_unpacker_t;
28
+ typedef struct msgpack_unpacker_t msgpack_unpacker_t;
29
+
30
+ enum stack_type_t {
31
+ STACK_TYPE_ARRAY,
32
+ STACK_TYPE_MAP_KEY,
33
+ STACK_TYPE_MAP_VALUE,
34
+ };
35
+
36
+ typedef struct {
37
+ size_t count;
38
+ enum stack_type_t type;
39
+ VALUE object;
40
+ VALUE key;
41
+ } msgpack_unpacker_stack_t;
42
+
43
+ #define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
44
+
45
+ struct msgpack_unpacker_t {
46
+ msgpack_buffer_t buffer;
47
+
48
+ unsigned int head_byte;
49
+
50
+ msgpack_unpacker_stack_t* stack;
51
+ size_t stack_depth;
52
+ size_t stack_capacity;
53
+
54
+ VALUE last_object;
55
+
56
+ VALUE reading_raw;
57
+ size_t reading_raw_remaining;
58
+
59
+ VALUE buffer_ref;
60
+
61
+ /* options */
62
+ bool symbolize_keys;
63
+ };
64
+
65
+ #define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
66
+
67
+ enum msgpack_unpacker_object_type {
68
+ TYPE_NIL = 0,
69
+ TYPE_BOOLEAN,
70
+ TYPE_INTEGER,
71
+ TYPE_FLOAT,
72
+ TYPE_RAW,
73
+ TYPE_ARRAY,
74
+ TYPE_MAP,
75
+ };
76
+
77
+ void msgpack_unpacker_static_init();
78
+
79
+ void msgpack_unpacker_static_destroy();
80
+
81
+ void msgpack_unpacker_init(msgpack_unpacker_t* uk);
82
+
83
+ void msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
84
+
85
+ void msgpack_unpacker_mark(msgpack_unpacker_t* uk);
86
+
87
+ void msgpack_unpacker_reset(msgpack_unpacker_t* uk);
88
+
89
+ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk, bool enable)
90
+ {
91
+ uk->symbolize_keys = enable;
92
+ }
93
+
94
+
95
+ /* error codes */
96
+ #define PRIMITIVE_CONTAINER_START 1
97
+ #define PRIMITIVE_OBJECT_COMPLETE 0
98
+ #define PRIMITIVE_EOF -1
99
+ #define PRIMITIVE_INVALID_BYTE -2
100
+ #define PRIMITIVE_STACK_TOO_DEEP -3
101
+ #define PRIMITIVE_UNEXPECTED_TYPE -4
102
+
103
+ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth);
104
+
105
+ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth);
106
+
107
+ static inline VALUE msgpack_unpacker_get_last_object(msgpack_unpacker_t* uk)
108
+ {
109
+ return uk->last_object;
110
+ }
111
+
112
+
113
+ int msgpack_unpacker_peek_next_object_type(msgpack_unpacker_t* uk);
114
+
115
+ int msgpack_unpacker_skip_nil(msgpack_unpacker_t* uk);
116
+
117
+ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_size);
118
+
119
+ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_size);
120
+
121
+ #endif
122
+
@@ -0,0 +1,405 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "unpacker.h"
20
+ #include "unpacker_class.h"
21
+ #include "buffer_class.h"
22
+
23
+ VALUE cMessagePack_Unpacker;
24
+
25
+ //static VALUE s_unpacker_value;
26
+ //static msgpack_unpacker_t* s_unpacker;
27
+
28
+ static VALUE eUnpackError;
29
+ static VALUE eMalformedFormatError;
30
+ static VALUE eStackError;
31
+ static VALUE eTypeError;
32
+
33
+ #define UNPACKER(from, name) \
34
+ msgpack_unpacker_t *name = NULL; \
35
+ Data_Get_Struct(from, msgpack_unpacker_t, name); \
36
+ if(name == NULL) { \
37
+ rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
38
+ }
39
+
40
+ static void Unpacker_free(msgpack_unpacker_t* uk)
41
+ {
42
+ if(uk == NULL) {
43
+ return;
44
+ }
45
+ msgpack_unpacker_destroy(uk);
46
+ free(uk);
47
+ }
48
+
49
+ static VALUE Unpacker_alloc(VALUE klass)
50
+ {
51
+ msgpack_unpacker_t* uk = ALLOC_N(msgpack_unpacker_t, 1);
52
+ msgpack_unpacker_init(uk);
53
+
54
+ VALUE self = Data_Wrap_Struct(klass, msgpack_unpacker_mark, Unpacker_free, uk);
55
+
56
+ uk->buffer_ref = MessagePack_Buffer_wrap(UNPACKER_BUFFER_(uk), self);
57
+
58
+ return self;
59
+ }
60
+
61
+ static VALUE Unpacker_initialize(int argc, VALUE* argv, VALUE self)
62
+ {
63
+ VALUE io = Qnil;
64
+ VALUE options = Qnil;
65
+
66
+ if(argc == 0 || (argc == 1 && argv[0] == Qnil)) {
67
+ /* Qnil */
68
+
69
+ } else if(argc == 1) {
70
+ VALUE v = argv[0];
71
+ if(rb_type(v) == T_HASH) {
72
+ options = v;
73
+ if(rb_type(options) != T_HASH) {
74
+ rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
75
+ }
76
+ } else {
77
+ io = v;
78
+ }
79
+
80
+ } else if(argc == 2) {
81
+ io = argv[0];
82
+ options = argv[1];
83
+ if(rb_type(options) != T_HASH) {
84
+ rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
85
+ }
86
+
87
+ } else {
88
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
89
+ }
90
+
91
+ UNPACKER(self, uk);
92
+
93
+ MessagePack_Unpacker_initialize(uk, io, options);
94
+
95
+ return self;
96
+ }
97
+
98
+ void MessagePack_Unpacker_initialize(msgpack_unpacker_t* uk, VALUE io, VALUE options)
99
+ {
100
+ MessagePack_Buffer_initialize(UNPACKER_BUFFER_(uk), io, options);
101
+
102
+ if(options != Qnil) {
103
+ VALUE v;
104
+
105
+ v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
106
+ msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
107
+ }
108
+ }
109
+
110
+ static void raise_unpacker_error(int r)
111
+ {
112
+ switch(r) {
113
+ case PRIMITIVE_EOF:
114
+ rb_raise(rb_eEOFError, "end of buffer reached");
115
+ case PRIMITIVE_INVALID_BYTE:
116
+ rb_raise(eMalformedFormatError, "invalid byte");
117
+ case PRIMITIVE_STACK_TOO_DEEP:
118
+ rb_raise(eStackError, "stack level too deep");
119
+ case PRIMITIVE_UNEXPECTED_TYPE:
120
+ rb_raise(eTypeError, "unexpected type");
121
+ default:
122
+ rb_raise(eUnpackError, "logically unknown error %d", r);
123
+ }
124
+ }
125
+
126
+ static VALUE Unpacker_buffer(VALUE self)
127
+ {
128
+ UNPACKER(self, uk);
129
+ return uk->buffer_ref;
130
+ }
131
+
132
+ static VALUE Unpacker_read(VALUE self)
133
+ {
134
+ UNPACKER(self, uk);
135
+
136
+ int r = msgpack_unpacker_read(uk, 0);
137
+ if(r < 0) {
138
+ raise_unpacker_error(r);
139
+ }
140
+
141
+ return msgpack_unpacker_get_last_object(uk);
142
+ }
143
+
144
+ static VALUE Unpacker_skip(VALUE self)
145
+ {
146
+ UNPACKER(self, uk);
147
+
148
+ int r = msgpack_unpacker_skip(uk, 0);
149
+ if(r < 0) {
150
+ raise_unpacker_error(r);
151
+ }
152
+
153
+ return Qnil;
154
+ }
155
+
156
+ static VALUE Unpacker_skip_nil(VALUE self)
157
+ {
158
+ UNPACKER(self, uk);
159
+
160
+ int r = msgpack_unpacker_skip_nil(uk);
161
+ if(r < 0) {
162
+ raise_unpacker_error(r);
163
+ }
164
+
165
+ if(r) {
166
+ return Qtrue;
167
+ }
168
+ return Qfalse;
169
+ }
170
+
171
+ static VALUE Unpacker_read_array_header(VALUE self)
172
+ {
173
+ UNPACKER(self, uk);
174
+
175
+ uint32_t size;
176
+ int r = msgpack_unpacker_read_array_header(uk, &size);
177
+ if(r < 0) {
178
+ raise_unpacker_error(r);
179
+ }
180
+
181
+ return ULONG2NUM(size);
182
+ }
183
+
184
+ static VALUE Unpacker_read_map_header(VALUE self)
185
+ {
186
+ UNPACKER(self, uk);
187
+
188
+ uint32_t size;
189
+ int r = msgpack_unpacker_read_map_header(uk, &size);
190
+ if(r < 0) {
191
+ raise_unpacker_error((int)r);
192
+ }
193
+
194
+ return ULONG2NUM(size);
195
+ }
196
+
197
+ static VALUE Unpacker_peek_next_type(VALUE self)
198
+ {
199
+ UNPACKER(self, uk);
200
+
201
+ int r = msgpack_unpacker_peek_next_object_type(uk);
202
+ if(r < 0) {
203
+ raise_unpacker_error(r);
204
+ }
205
+
206
+ switch((enum msgpack_unpacker_object_type) r) {
207
+ case TYPE_NIL:
208
+ return rb_intern("nil");
209
+ case TYPE_BOOLEAN:
210
+ return rb_intern("boolean");
211
+ case TYPE_INTEGER:
212
+ return rb_intern("integer");
213
+ case TYPE_FLOAT:
214
+ return rb_intern("float");
215
+ case TYPE_RAW:
216
+ return rb_intern("raw");
217
+ case TYPE_ARRAY:
218
+ return rb_intern("array");
219
+ case TYPE_MAP:
220
+ return rb_intern("map");
221
+ default:
222
+ rb_raise(eUnpackError, "logically unknown type %d", r);
223
+ }
224
+ }
225
+
226
+ static VALUE Unpacker_feed(VALUE self, VALUE data)
227
+ {
228
+ UNPACKER(self, uk);
229
+
230
+ StringValue(data);
231
+
232
+ msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), data);
233
+
234
+ return self;
235
+ }
236
+
237
+ static VALUE Unpacker_each_impl(VALUE self)
238
+ {
239
+ UNPACKER(self, uk);
240
+
241
+ while(true) {
242
+ int r = msgpack_unpacker_read(uk, 0);
243
+ if(r < 0) {
244
+ if(r == PRIMITIVE_EOF) {
245
+ return Qnil;
246
+ }
247
+ raise_unpacker_error(r);
248
+ }
249
+ VALUE v = msgpack_unpacker_get_last_object(uk);
250
+ #ifdef JRUBY
251
+ /* TODO JRuby's rb_yield behaves differently from Ruby 1.9.3 or Rubinius. */
252
+ if(rb_type(v) == T_ARRAY) {
253
+ v = rb_ary_new3(1, v);
254
+ }
255
+ #endif
256
+ rb_yield(v);
257
+ }
258
+ }
259
+
260
+ static VALUE Unpacker_rescue_EOFError(VALUE self)
261
+ {
262
+ UNUSED(self);
263
+ return Qnil;
264
+ }
265
+
266
+ static VALUE Unpacker_each(VALUE self)
267
+ {
268
+ UNPACKER(self, uk);
269
+
270
+ #ifdef RETURN_ENUMERATOR
271
+ RETURN_ENUMERATOR(self, 0, 0);
272
+ #endif
273
+
274
+ if(msgpack_buffer_has_io(UNPACKER_BUFFER_(uk))) {
275
+ /* rescue EOFError only if io is set */
276
+ return rb_rescue2(Unpacker_each_impl, self,
277
+ Unpacker_rescue_EOFError, self,
278
+ rb_eEOFError, NULL);
279
+ } else {
280
+ return Unpacker_each_impl(self);
281
+ }
282
+ }
283
+
284
+ static VALUE Unpacker_feed_each(VALUE self, VALUE data)
285
+ {
286
+ // TODO optimize
287
+ Unpacker_feed(self, data);
288
+ return Unpacker_each(self);
289
+ }
290
+
291
+ static VALUE Unpacker_reset(VALUE self)
292
+ {
293
+ UNPACKER(self, uk);
294
+
295
+ msgpack_unpacker_reset(uk);
296
+
297
+ return Qnil;
298
+ }
299
+
300
+ VALUE MessagePack_unpack(int argc, VALUE* argv)
301
+ {
302
+ VALUE src;
303
+ VALUE options = Qnil;
304
+
305
+ switch(argc) {
306
+ case 2:
307
+ options = argv[1];
308
+ if(rb_type(options) != T_HASH) {
309
+ rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
310
+ }
311
+ /* pass-through */
312
+ case 1:
313
+ src = argv[0];
314
+ break;
315
+ default:
316
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
317
+ }
318
+
319
+ VALUE self = Unpacker_alloc(cMessagePack_Unpacker);
320
+ UNPACKER(self, uk);
321
+ //msgpack_unpacker_reset(s_unpacker);
322
+ //msgpack_buffer_reset_io(UNPACKER_BUFFER_(s_unpacker));
323
+
324
+ /* prefer reference than copying; see MessagePack_Unpacker_module_init */
325
+ msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(uk), 0);
326
+
327
+ if(rb_type(src) == T_STRING) {
328
+ MessagePack_Unpacker_initialize(uk, Qnil, options);
329
+ msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), src);
330
+ } else {
331
+ MessagePack_Unpacker_initialize(uk, src, options);
332
+ }
333
+
334
+ int r = msgpack_unpacker_read(uk, 0);
335
+ if(r < 0) {
336
+ raise_unpacker_error(r);
337
+ }
338
+
339
+ /* raise if extra bytes follow */
340
+ if(msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk)) > 0) {
341
+ rb_raise(eMalformedFormatError, "extra bytes follow after a deserialized object");
342
+ }
343
+
344
+ #ifdef RB_GC_GUARD
345
+ /* This prevents compilers from optimizing out the `self` variable
346
+ * from stack. Otherwise GC free()s it. */
347
+ RB_GC_GUARD(self);
348
+ #endif
349
+
350
+ return msgpack_unpacker_get_last_object(uk);
351
+ }
352
+
353
+ static VALUE MessagePack_load_module_method(int argc, VALUE* argv, VALUE mod)
354
+ {
355
+ UNUSED(mod);
356
+ return MessagePack_unpack(argc, argv);
357
+ }
358
+
359
+ static VALUE MessagePack_unpack_module_method(int argc, VALUE* argv, VALUE mod)
360
+ {
361
+ UNUSED(mod);
362
+ return MessagePack_unpack(argc, argv);
363
+ }
364
+
365
+ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
366
+ {
367
+ msgpack_unpacker_static_init();
368
+
369
+ cMessagePack_Unpacker = rb_define_class_under(mMessagePack, "Unpacker", rb_cObject);
370
+
371
+ eUnpackError = rb_define_class_under(mMessagePack, "UnpackError", rb_eStandardError);
372
+
373
+ eMalformedFormatError = rb_define_class_under(mMessagePack, "MalformedFormatError", eUnpackError);
374
+
375
+ eStackError = rb_define_class_under(mMessagePack, "StackError", eUnpackError);
376
+
377
+ eTypeError = rb_define_class_under(mMessagePack, "TypeError", rb_eStandardError);
378
+
379
+ rb_define_alloc_func(cMessagePack_Unpacker, Unpacker_alloc);
380
+
381
+ rb_define_method(cMessagePack_Unpacker, "initialize", Unpacker_initialize, -1);
382
+ rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
383
+ rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
384
+ rb_define_alias(cMessagePack_Unpacker, "unpack", "read");
385
+ rb_define_method(cMessagePack_Unpacker, "skip", Unpacker_skip, 0);
386
+ rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
387
+ rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
388
+ rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
389
+ //rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
390
+ rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
391
+ rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
392
+ rb_define_method(cMessagePack_Unpacker, "feed_each", Unpacker_feed_each, 1);
393
+ rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 0);
394
+
395
+ //s_unpacker_value = Unpacker_alloc(cMessagePack_Unpacker);
396
+ //rb_gc_register_address(&s_unpacker_value);
397
+ //Data_Get_Struct(s_unpacker_value, msgpack_unpacker_t, s_unpacker);
398
+ /* prefer reference than copying */
399
+ //msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(s_unpacker), 0);
400
+
401
+ /* MessagePack.unpack(x) */
402
+ rb_define_module_function(mMessagePack, "load", MessagePack_load_module_method, -1);
403
+ rb_define_module_function(mMessagePack, "unpack", MessagePack_unpack_module_method, -1);
404
+ }
405
+