msgpack 1.3.3 → 1.6.0

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/.rubocop.yml +2 -2
  4. data/ChangeLog +74 -0
  5. data/Gemfile +1 -1
  6. data/README.md +266 -0
  7. data/Rakefile +1 -9
  8. data/bench/bench.rb +78 -0
  9. data/bin/console +8 -0
  10. data/doclib/msgpack/factory.rb +47 -3
  11. data/doclib/msgpack/packer.rb +5 -4
  12. data/doclib/msgpack/unpacker.rb +2 -2
  13. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  14. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  15. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  16. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  17. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  18. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  19. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  20. data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
  21. data/ext/msgpack/buffer.c +42 -68
  22. data/ext/msgpack/buffer.h +59 -14
  23. data/ext/msgpack/buffer_class.c +90 -52
  24. data/ext/msgpack/compat.h +1 -111
  25. data/ext/msgpack/extconf.rb +45 -19
  26. data/ext/msgpack/factory_class.c +133 -43
  27. data/ext/msgpack/packer.c +60 -36
  28. data/ext/msgpack/packer.h +27 -25
  29. data/ext/msgpack/packer_class.c +84 -77
  30. data/ext/msgpack/packer_class.h +11 -0
  31. data/ext/msgpack/packer_ext_registry.c +24 -32
  32. data/ext/msgpack/packer_ext_registry.h +40 -33
  33. data/ext/msgpack/sysdep.h +5 -2
  34. data/ext/msgpack/unpacker.c +132 -115
  35. data/ext/msgpack/unpacker.h +23 -10
  36. data/ext/msgpack/unpacker_class.c +83 -78
  37. data/ext/msgpack/unpacker_class.h +11 -0
  38. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  39. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  40. data/lib/msgpack/bigint.rb +69 -0
  41. data/lib/msgpack/factory.rb +103 -0
  42. data/lib/msgpack/symbol.rb +21 -4
  43. data/lib/msgpack/time.rb +1 -1
  44. data/lib/msgpack/version.rb +4 -8
  45. data/lib/msgpack.rb +6 -12
  46. data/msgpack.gemspec +4 -6
  47. data/spec/bigint_spec.rb +26 -0
  48. data/spec/cruby/buffer_spec.rb +17 -0
  49. data/spec/factory_spec.rb +351 -12
  50. data/spec/msgpack_spec.rb +1 -1
  51. data/spec/packer_spec.rb +18 -0
  52. data/spec/spec_helper.rb +37 -3
  53. data/spec/timestamp_spec.rb +38 -0
  54. data/spec/unpacker_spec.rb +157 -4
  55. metadata +31 -61
  56. data/.travis.yml +0 -43
  57. data/README.rdoc +0 -225
  58. data/bench/pack.rb +0 -23
  59. data/bench/pack_log.rb +0 -33
  60. data/bench/pack_log_long.rb +0 -65
  61. data/bench/pack_symbols.rb +0 -28
  62. data/bench/run.sh +0 -14
  63. data/bench/run_long.sh +0 -35
  64. data/bench/run_symbols.sh +0 -26
  65. data/bench/unpack.rb +0 -21
  66. data/bench/unpack_log.rb +0 -34
  67. data/bench/unpack_log_long.rb +0 -67
@@ -30,47 +30,76 @@ typedef struct msgpack_factory_t msgpack_factory_t;
30
30
 
31
31
  struct msgpack_factory_t {
32
32
  msgpack_packer_ext_registry_t pkrg;
33
- msgpack_unpacker_ext_registry_t ukrg;
33
+ msgpack_unpacker_ext_registry_t *ukrg;
34
+ bool has_bigint_ext_type;
34
35
  bool has_symbol_ext_type;
36
+ bool optimized_symbol_ext_type;
37
+ int symbol_ext_type;
35
38
  };
36
39
 
37
- #define FACTORY(from, name) \
38
- msgpack_factory_t *name = NULL; \
39
- Data_Get_Struct(from, msgpack_factory_t, name); \
40
- if(name == NULL) { \
41
- rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
42
- }
43
-
44
- static void Factory_free(msgpack_factory_t* fc)
40
+ static void Factory_free(void *ptr)
45
41
  {
42
+ msgpack_factory_t *fc = ptr;
43
+
46
44
  if(fc == NULL) {
47
45
  return;
48
46
  }
49
47
  msgpack_packer_ext_registry_destroy(&fc->pkrg);
50
- msgpack_unpacker_ext_registry_destroy(&fc->ukrg);
48
+ msgpack_unpacker_ext_registry_release(fc->ukrg);
51
49
  xfree(fc);
52
50
  }
53
51
 
54
- void Factory_mark(msgpack_factory_t* fc)
52
+ void Factory_mark(void *ptr)
55
53
  {
54
+ msgpack_factory_t *fc = ptr;
56
55
  msgpack_packer_ext_registry_mark(&fc->pkrg);
57
- msgpack_unpacker_ext_registry_mark(&fc->ukrg);
56
+ msgpack_unpacker_ext_registry_mark(fc->ukrg);
58
57
  }
59
58
 
60
- static VALUE Factory_alloc(VALUE klass)
59
+ static size_t Factory_memsize(const void *ptr)
61
60
  {
62
- msgpack_factory_t* fc = ZALLOC_N(msgpack_factory_t, 1);
61
+ const msgpack_factory_t *fc = ptr;
62
+ size_t total_size = sizeof(msgpack_factory_t);
63
63
 
64
- VALUE self = Data_Wrap_Struct(klass, Factory_mark, Factory_free, fc);
65
- return self;
64
+ if (fc->ukrg) {
65
+ total_size += sizeof(msgpack_unpacker_ext_registry_t) / (fc->ukrg->borrow_count + 1);
66
+ }
67
+
68
+ return total_size;
69
+ }
70
+
71
+ static const rb_data_type_t factory_data_type = {
72
+ .wrap_struct_name = "msgpack:factory",
73
+ .function = {
74
+ .dmark = Factory_mark,
75
+ .dfree = Factory_free,
76
+ .dsize = Factory_memsize,
77
+ },
78
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
79
+ };
80
+
81
+ static inline msgpack_factory_t *Factory_get(VALUE object)
82
+ {
83
+ msgpack_factory_t *factory;
84
+ TypedData_Get_Struct(object, msgpack_factory_t, &factory_data_type, factory);
85
+ if (!factory) {
86
+ rb_raise(rb_eArgError, "Uninitialized Factory object");
87
+ }
88
+ return factory;
89
+ }
90
+
91
+ static VALUE Factory_alloc(VALUE klass)
92
+ {
93
+ msgpack_factory_t *fc;
94
+ return TypedData_Make_Struct(klass, msgpack_factory_t, &factory_data_type, fc);
66
95
  }
67
96
 
68
97
  static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
69
98
  {
70
- FACTORY(self, fc);
99
+ msgpack_factory_t *fc = Factory_get(self);
71
100
 
72
101
  msgpack_packer_ext_registry_init(&fc->pkrg);
73
- msgpack_unpacker_ext_registry_init(&fc->ukrg);
102
+ // fc->ukrg is lazily initialized
74
103
 
75
104
  fc->has_symbol_ext_type = false;
76
105
 
@@ -85,18 +114,52 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
85
114
  return Qnil;
86
115
  }
87
116
 
117
+ static VALUE Factory_dup(VALUE self)
118
+ {
119
+ VALUE clone = Factory_alloc(rb_obj_class(self));
120
+
121
+ msgpack_factory_t *fc = Factory_get(self);
122
+ msgpack_factory_t *cloned_fc = Factory_get(clone);
123
+
124
+ cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
125
+ cloned_fc->pkrg = fc->pkrg;
126
+ msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
127
+ msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
128
+
129
+ return clone;
130
+ }
131
+
132
+ static VALUE Factory_freeze(VALUE self) {
133
+ if(!rb_obj_frozen_p(self)) {
134
+ msgpack_factory_t *fc = Factory_get(self);
135
+
136
+ if (RTEST(fc->pkrg.hash)) {
137
+ rb_hash_freeze(fc->pkrg.hash);
138
+ if (!RTEST(fc->pkrg.cache)) {
139
+ // If the factory is frozen, we can safely share the packer cache between
140
+ // all packers. So we eagerly create it now so it's available when #packer
141
+ // is called.
142
+ fc->pkrg.cache = rb_hash_new();
143
+ }
144
+ }
145
+
146
+ rb_obj_freeze(self);
147
+ }
148
+
149
+ return self;
150
+ }
151
+
88
152
  VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
89
153
  {
90
- FACTORY(self, fc);
154
+ msgpack_factory_t *fc = Factory_get(self);
91
155
 
92
156
  VALUE packer = MessagePack_Packer_alloc(cMessagePack_Packer);
93
157
  MessagePack_Packer_initialize(argc, argv, packer);
94
158
 
95
- msgpack_packer_t* pk;
96
- Data_Get_Struct(packer, msgpack_packer_t, pk);
97
-
159
+ msgpack_packer_t* pk = MessagePack_Packer_get(packer);
98
160
  msgpack_packer_ext_registry_destroy(&pk->ext_registry);
99
161
  msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
162
+ pk->has_bigint_ext_type = fc->has_bigint_ext_type;
100
163
  pk->has_symbol_ext_type = fc->has_symbol_ext_type;
101
164
 
102
165
  return packer;
@@ -104,44 +167,47 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
104
167
 
105
168
  VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
106
169
  {
107
- FACTORY(self, fc);
170
+ msgpack_factory_t *fc = Factory_get(self);
108
171
 
109
172
  VALUE unpacker = MessagePack_Unpacker_alloc(cMessagePack_Unpacker);
110
173
  MessagePack_Unpacker_initialize(argc, argv, unpacker);
111
174
 
112
- msgpack_unpacker_t* uk;
113
- Data_Get_Struct(unpacker, msgpack_unpacker_t, uk);
114
-
115
- msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
116
- msgpack_unpacker_ext_registry_dup(&fc->ukrg, &uk->ext_registry);
175
+ msgpack_unpacker_t* uk = MessagePack_Unpacker_get(unpacker);
176
+ msgpack_unpacker_ext_registry_borrow(fc->ukrg, &uk->ext_registry);
177
+ uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
178
+ uk->symbol_ext_type = fc->symbol_ext_type;
117
179
 
118
180
  return unpacker;
119
181
  }
120
182
 
121
183
  static VALUE Factory_registered_types_internal(VALUE self)
122
184
  {
123
- FACTORY(self, fc);
185
+ msgpack_factory_t *fc = Factory_get(self);
124
186
 
125
187
  VALUE uk_mapping = rb_hash_new();
126
- for(int i=0; i < 256; i++) {
127
- if(fc->ukrg.array[i] != Qnil) {
128
- rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg.array[i]);
188
+ if (fc->ukrg) {
189
+ for(int i=0; i < 256; i++) {
190
+ if(fc->ukrg->array[i] != Qnil) {
191
+ rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
192
+ }
129
193
  }
130
194
  }
131
- #ifdef HAVE_RB_HASH_DUP
132
- return rb_ary_new3(2, rb_hash_dup(fc->pkrg.hash), uk_mapping);
133
- #else
134
- return rb_ary_new3(2, rb_funcall(fc->pkrg.hash, rb_intern("dup"), 0), uk_mapping);
135
- #endif
195
+
196
+ return rb_ary_new3(
197
+ 2,
198
+ RTEST(fc->pkrg.hash) ? rb_hash_dup(fc->pkrg.hash) : rb_hash_new(),
199
+ uk_mapping
200
+ );
136
201
  }
137
202
 
138
203
  static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
139
204
  {
140
- FACTORY(self, fc);
205
+ msgpack_factory_t *fc = Factory_get(self);
141
206
 
142
207
  int ext_type;
208
+ int flags = 0;
143
209
  VALUE ext_module;
144
- VALUE options;
210
+ VALUE options = Qnil;
145
211
  VALUE packer_arg, unpacker_arg;
146
212
  VALUE packer_proc, unpacker_proc;
147
213
 
@@ -168,6 +234,10 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
168
234
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
169
235
  }
170
236
 
237
+ if (options != Qnil) {
238
+ Check_Type(options, T_HASH);
239
+ }
240
+
171
241
  ext_type = NUM2INT(argv[0]);
172
242
  if(ext_type < -128 || ext_type > 127) {
173
243
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
@@ -188,18 +258,36 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
188
258
  if(unpacker_arg != Qnil) {
189
259
  if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
190
260
  unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
261
+ } else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
262
+ unpacker_proc = unpacker_arg;
191
263
  } else {
192
264
  unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
193
265
  }
194
266
  }
195
267
 
196
- msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, packer_proc, packer_arg);
197
-
198
- if (ext_module == rb_cSymbol) {
268
+ if(ext_module == rb_cSymbol) {
199
269
  fc->has_symbol_ext_type = true;
270
+ if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
271
+ fc->optimized_symbol_ext_type = true;
272
+ }
273
+ }
274
+
275
+ if(RTEST(options)) {
276
+ if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("oversized_integer_extension"))))) {
277
+ if(ext_module == rb_cInteger) {
278
+ fc->has_bigint_ext_type = true;
279
+ } else {
280
+ rb_raise(rb_eArgError, "oversized_integer_extension: true is only for Integer class");
281
+ }
282
+ }
283
+
284
+ if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("recursive"))))) {
285
+ flags |= MSGPACK_EXT_RECURSIVE;
286
+ }
200
287
  }
201
288
 
202
- msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, unpacker_proc, unpacker_arg);
289
+ msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
290
+ msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
203
291
 
204
292
  return Qnil;
205
293
  }
@@ -211,6 +299,8 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
211
299
  rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
212
300
 
213
301
  rb_define_method(cMessagePack_Factory, "initialize", Factory_initialize, -1);
302
+ rb_define_method(cMessagePack_Factory, "dup", Factory_dup, 0);
303
+ rb_define_method(cMessagePack_Factory, "freeze", Factory_freeze, 0);
214
304
 
215
305
  rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
216
306
  rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
data/ext/msgpack/packer.c CHANGED
@@ -18,34 +18,18 @@
18
18
 
19
19
  #include "packer.h"
20
20
 
21
- #ifdef RUBINIUS
22
- static ID s_to_iter;
23
- static ID s_next;
24
- static ID s_key;
25
- static ID s_value;
26
- #endif
27
-
28
21
  static ID s_call;
29
22
 
30
- void msgpack_packer_static_init()
23
+ void msgpack_packer_static_init(void)
31
24
  {
32
- #ifdef RUBINIUS
33
- s_to_iter = rb_intern("to_iter");
34
- s_next = rb_intern("next");
35
- s_key = rb_intern("key");
36
- s_value = rb_intern("value");
37
- #endif
38
-
39
25
  s_call = rb_intern("call");
40
26
  }
41
27
 
42
- void msgpack_packer_static_destroy()
28
+ void msgpack_packer_static_destroy(void)
43
29
  { }
44
30
 
45
31
  void msgpack_packer_init(msgpack_packer_t* pk)
46
32
  {
47
- memset(pk, 0, sizeof(msgpack_packer_t));
48
-
49
33
  msgpack_buffer_init(PACKER_BUFFER_(pk));
50
34
  }
51
35
 
@@ -108,30 +92,64 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
108
92
  unsigned int len32 = (unsigned int)len;
109
93
  msgpack_packer_write_map_header(pk, len32);
110
94
 
111
- #ifdef RUBINIUS
112
- VALUE iter = rb_funcall(v, s_to_iter, 0);
113
- VALUE entry = Qnil;
114
- while(RTEST(entry = rb_funcall(iter, s_next, 1, entry))) {
115
- VALUE key = rb_funcall(entry, s_key, 0);
116
- VALUE val = rb_funcall(entry, s_value, 0);
117
- write_hash_foreach(key, val, (VALUE) pk);
118
- }
119
- #else
120
95
  rb_hash_foreach(v, write_hash_foreach, (VALUE) pk);
121
- #endif
122
96
  }
123
97
 
124
- void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
98
+ struct msgpack_call_proc_args_t;
99
+ typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
100
+ struct msgpack_call_proc_args_t {
101
+ VALUE proc;
102
+ VALUE arg;
103
+ VALUE packer;
104
+ };
105
+
106
+ VALUE msgpack_packer_try_calling_proc(VALUE value)
125
107
  {
126
- int ext_type;
108
+ msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
109
+ return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
110
+ }
127
111
 
128
- VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type);
112
+ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
113
+ {
114
+ int ext_type, ext_flags;
129
115
 
130
- if(proc != Qnil) {
116
+ VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
117
+
118
+ if(proc == Qnil) {
119
+ return false;
120
+ }
121
+
122
+ if(ext_flags & MSGPACK_EXT_RECURSIVE) {
123
+ msgpack_buffer_t parent_buffer = pk->buffer;
124
+ msgpack_buffer_init(PACKER_BUFFER_(pk));
125
+
126
+ int exception_occured = 0;
127
+ msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
128
+ rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
129
+
130
+ if (exception_occured) {
131
+ msgpack_buffer_destroy(PACKER_BUFFER_(pk));
132
+ pk->buffer = parent_buffer;
133
+ rb_jump_tag(exception_occured); // re-raise the exception
134
+ } else {
135
+ VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
136
+ StringValue(payload);
137
+ msgpack_buffer_destroy(PACKER_BUFFER_(pk));
138
+ pk->buffer = parent_buffer;
139
+ msgpack_packer_write_ext(pk, ext_type, payload);
140
+ }
141
+ } else {
131
142
  VALUE payload = rb_funcall(proc, s_call, 1, v);
132
143
  StringValue(payload);
133
144
  msgpack_packer_write_ext(pk, ext_type, payload);
134
- } else {
145
+ }
146
+
147
+ return true;
148
+ }
149
+
150
+ void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
151
+ {
152
+ if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
135
153
  rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
136
154
  }
137
155
  }
@@ -155,13 +173,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
155
173
  msgpack_packer_write_symbol_value(pk, v);
156
174
  break;
157
175
  case T_STRING:
158
- msgpack_packer_write_string_value(pk, v);
176
+ if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
177
+ msgpack_packer_write_string_value(pk, v);
178
+ }
159
179
  break;
160
180
  case T_ARRAY:
161
- msgpack_packer_write_array_value(pk, v);
181
+ if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
182
+ msgpack_packer_write_array_value(pk, v);
183
+ }
162
184
  break;
163
185
  case T_HASH:
164
- msgpack_packer_write_hash_value(pk, v);
186
+ if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
187
+ msgpack_packer_write_hash_value(pk, v);
188
+ }
165
189
  break;
166
190
  case T_BIGNUM:
167
191
  msgpack_packer_write_bignum_value(pk, v);
data/ext/msgpack/packer.h CHANGED
@@ -32,6 +32,7 @@ struct msgpack_packer_t {
32
32
  msgpack_buffer_t buffer;
33
33
 
34
34
  bool compatibility_mode;
35
+ bool has_bigint_ext_type;
35
36
  bool has_symbol_ext_type;
36
37
 
37
38
  ID to_msgpack_method;
@@ -46,9 +47,9 @@ struct msgpack_packer_t {
46
47
 
47
48
  #define PACKER_BUFFER_(pk) (&(pk)->buffer)
48
49
 
49
- void msgpack_packer_static_init();
50
+ void msgpack_packer_static_init(void);
50
51
 
51
- void msgpack_packer_static_destroy();
52
+ void msgpack_packer_static_destroy(void);
52
53
 
53
54
  void msgpack_packer_init(msgpack_packer_t* pk);
54
55
 
@@ -56,6 +57,8 @@ void msgpack_packer_destroy(msgpack_packer_t* pk);
56
57
 
57
58
  void msgpack_packer_mark(msgpack_packer_t* pk);
58
59
 
60
+ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v);
61
+
59
62
  static inline void msgpack_packer_set_to_msgpack_method(msgpack_packer_t* pk,
60
63
  ID to_msgpack_method, VALUE to_msgpack_arg)
61
64
  {
@@ -396,7 +399,6 @@ static inline void msgpack_packer_write_ext(msgpack_packer_t* pk, int ext_type,
396
399
  msgpack_buffer_append_string(PACKER_BUFFER_(pk), payload);
397
400
  }
398
401
 
399
- #ifdef COMPAT_HAVE_ENCODING
400
402
  static inline bool msgpack_packer_is_binary(VALUE v, int encindex)
401
403
  {
402
404
  return encindex == msgpack_rb_encindex_ascii8bit;
@@ -406,15 +408,8 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
406
408
  {
407
409
  return encindex == msgpack_rb_encindex_utf8
408
410
  || encindex == msgpack_rb_encindex_usascii
409
- #ifdef ENC_CODERANGE_ASCIIONLY
410
- /* Because ENC_CODERANGE_ASCIIONLY does not scan string, it may return ENC_CODERANGE_UNKNOWN unlike */
411
- /* rb_enc_str_asciionly_p. It is always faster than rb_str_encode if it is available. */
412
- /* Very old Rubinius (< v1.3.1) doesn't have ENC_CODERANGE_ASCIIONLY. */
413
- || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v))
414
- #endif
415
- ;
411
+ || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
416
412
  }
417
- #endif
418
413
 
419
414
  static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
420
415
  {
@@ -425,7 +420,6 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
425
420
  rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
426
421
  }
427
422
 
428
- #ifdef COMPAT_HAVE_ENCODING
429
423
  int encindex = ENCODING_GET(v);
430
424
  if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
431
425
  /* write ASCII-8BIT string using Binary type */
@@ -443,24 +437,11 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
443
437
  msgpack_packer_write_raw_header(pk, (unsigned int)len);
444
438
  msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
445
439
  }
446
- #else
447
- msgpack_packer_write_raw_header(pk, (unsigned int)len);
448
- msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
449
- #endif
450
440
  }
451
441
 
452
442
  static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
453
443
  {
454
- #ifdef HAVE_RB_SYM2STR
455
- /* rb_sym2str is added since MRI 2.2.0 */
456
444
  msgpack_packer_write_string_value(pk, rb_sym2str(v));
457
- #else
458
- VALUE str = rb_id2str(SYM2ID(v));
459
- if (!str) {
460
- rb_raise(rb_eRuntimeError, "could not convert a symbol to string");
461
- }
462
- msgpack_packer_write_string_value(pk, str);
463
- #endif
464
445
  }
465
446
 
466
447
  void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
@@ -485,9 +466,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
485
466
 
486
467
  static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
487
468
  {
469
+ int leading_zero_bits;
470
+ size_t required_size = rb_absint_size(v, &leading_zero_bits);
471
+
488
472
  if(RBIGNUM_POSITIVE_P(v)) {
473
+ if(required_size > 8 && pk->has_bigint_ext_type) {
474
+ if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
475
+ return;
476
+ }
477
+ // if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
478
+ }
479
+
489
480
  msgpack_packer_write_u64(pk, rb_big2ull(v));
490
481
  } else {
482
+ if(leading_zero_bits == 0) {
483
+ required_size += 1;
484
+ }
485
+
486
+ if(required_size > 8 && pk->has_bigint_ext_type) {
487
+ if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
488
+ return;
489
+ }
490
+ // if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
491
+ }
492
+
491
493
  msgpack_packer_write_long_long(pk, rb_big2ll(v));
492
494
  }
493
495
  }