msgpack 1.3.3 → 1.6.0

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