msgpack 1.6.1 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +14 -0
- data/README.md +27 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +3 -3
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +2 -2
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +1 -1
- data/ext/java/org/msgpack/jruby/Factory.java +11 -7
- data/ext/java/org/msgpack/jruby/Packer.java +6 -4
- data/ext/java/org/msgpack/jruby/Unpacker.java +7 -8
- data/ext/msgpack/buffer.c +9 -12
- data/ext/msgpack/buffer.h +2 -10
- data/ext/msgpack/extconf.rb +15 -24
- data/ext/msgpack/factory_class.c +6 -3
- data/ext/msgpack/packer_class.c +10 -1
- data/ext/msgpack/rmem.c +3 -4
- data/ext/msgpack/unpacker.c +6 -21
- data/ext/msgpack/unpacker.h +0 -4
- data/ext/msgpack/unpacker_class.c +6 -14
- data/lib/msgpack/factory.rb +41 -53
- data/lib/msgpack/version.rb +1 -1
- data/msgpack.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2caf680ff4cafade89a14da270f52528ba2a862cea237ad028ba27fa6a93e9b
|
4
|
+
data.tar.gz: 01d8cc906d925acbd32a88c22f6ace7f5534a0b447be1736ea58cfdf9abb85b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48fcd12bfb13741d88a17e1a261cd742c903ba53cb1959a88b7083c2344817d90cfa898e775c136d785fbfcdd76be14b6dc5fc8ba3638a13ecabbb2d1387dbee
|
7
|
+
data.tar.gz: 310f3ea573cf41b15c47bc0033121496bd8ab7a723ef3667a96a38bc286feb79536ac5aeb8d27c3c71568149f93c8f36cc9ca8e050595e27ff87762cbccfe2dd
|
data/ChangeLog
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
2023-05-19 1.7.1:
|
2
|
+
|
3
|
+
* Fix JRuby 9.4 compatibility.
|
4
|
+
* Fix compilation on older compilers (gcc 4.x).
|
5
|
+
* Fix an infinite recursion issue when registering a Symbol type with a `nil` packer.
|
6
|
+
|
7
|
+
2023-03-29 1.7.0:
|
8
|
+
|
9
|
+
* Fix a possible double-free issue when GC triggers inside `_msgpack_rmem_alloc2`.
|
10
|
+
* `Unpacker#feed` now always directly read in provided strings instead of copying content in its buffer.
|
11
|
+
* `Unpacker#feed` is now an alias of `Unpacker#feed_reference`.
|
12
|
+
* Implement `Factory::Pool#unpacker` and `Factory::Pool#packer` to allow for more precise serialization.
|
13
|
+
* Require Ruby 2.5+.
|
14
|
+
|
1
15
|
2023-03-03 1.6.1:
|
2
16
|
|
3
17
|
* Undefine `#clone` and `#dup` on `MessagePack::Buffer`, `MessagePack::Packer` and `MessagePack::Unpacker`.
|
data/README.md
CHANGED
@@ -211,6 +211,33 @@ factory.register_type(
|
|
211
211
|
factory.load(factory.dump(Point.new(12, 34))) # => #<struct Point x=12, y=34>
|
212
212
|
```
|
213
213
|
|
214
|
+
## Pooling
|
215
|
+
|
216
|
+
Creating `Packer` and `Unpacker` objects is expensive. For best performance it is preferable to re-use these objects.
|
217
|
+
|
218
|
+
`MessagePack::Factory#pool` makes that easier:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
factory = MessagePack::Factory.new
|
222
|
+
factory.register_type(
|
223
|
+
0x01,
|
224
|
+
Point,
|
225
|
+
packer: ->(point, packer) {
|
226
|
+
packer.write(point.x)
|
227
|
+
packer.write(point.y)
|
228
|
+
},
|
229
|
+
unpacker: ->(unpacker) {
|
230
|
+
x = unpacker.read
|
231
|
+
y = unpacker.read
|
232
|
+
Point.new(x, y)
|
233
|
+
},
|
234
|
+
recursive: true,
|
235
|
+
)
|
236
|
+
pool = factory.pool(5) # The pool size should match the number of threads expected to use the factory concurrently.
|
237
|
+
|
238
|
+
pool.load(pool.dump(Point.new(12, 34))) # => #<struct Point x=12, y=34>
|
239
|
+
```
|
240
|
+
|
214
241
|
## Buffer API
|
215
242
|
|
216
243
|
MessagePack for Ruby provides a buffer API so that you can read or write data by hand, not via Packer or Unpacker API.
|
@@ -22,10 +22,10 @@ import org.jcodings.Encoding;
|
|
22
22
|
@JRubyClass(name="MessagePack::Buffer")
|
23
23
|
public class Buffer extends RubyObject {
|
24
24
|
private static final long serialVersionUID = 8441244627425629412L;
|
25
|
-
private IRubyObject io;
|
26
|
-
private ByteBuffer buffer;
|
25
|
+
private transient IRubyObject io;
|
26
|
+
private transient ByteBuffer buffer;
|
27
27
|
private boolean writeMode;
|
28
|
-
private Encoding binaryEncoding;
|
28
|
+
private transient Encoding binaryEncoding;
|
29
29
|
|
30
30
|
private static final int CACHE_LINE_SIZE = 64;
|
31
31
|
private static final int ARRAY_HEADER_SIZE = 24;
|
@@ -141,11 +141,11 @@ public class ExtensionRegistry {
|
|
141
141
|
}
|
142
142
|
|
143
143
|
public boolean hasPacker() {
|
144
|
-
return packerProc != null;
|
144
|
+
return packerProc != null && !packerProc.isNil();
|
145
145
|
}
|
146
146
|
|
147
147
|
public boolean hasUnpacker() {
|
148
|
-
return unpackerProc != null;
|
148
|
+
return unpackerProc != null && !unpackerProc.isNil();
|
149
149
|
}
|
150
150
|
|
151
151
|
public IRubyObject getPackerProc() {
|
@@ -26,7 +26,7 @@ import static org.msgpack.jruby.Types.*;
|
|
26
26
|
@JRubyClass(name="MessagePack::ExtensionValue")
|
27
27
|
public class ExtensionValue extends RubyObject {
|
28
28
|
private static final long serialVersionUID = 8451274621449322492L;
|
29
|
-
private final Encoding binaryEncoding;
|
29
|
+
private transient final Encoding binaryEncoding;
|
30
30
|
|
31
31
|
private RubyFixnum type;
|
32
32
|
private RubyString payload;
|
@@ -26,8 +26,8 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
26
26
|
@JRubyClass(name="MessagePack::Factory")
|
27
27
|
public class Factory extends RubyObject {
|
28
28
|
private static final long serialVersionUID = 8441284623445322492L;
|
29
|
-
private final Ruby runtime;
|
30
|
-
private ExtensionRegistry extensionRegistry;
|
29
|
+
private transient final Ruby runtime;
|
30
|
+
private transient ExtensionRegistry extensionRegistry;
|
31
31
|
private boolean hasSymbolExtType;
|
32
32
|
private boolean hasBigIntExtType;
|
33
33
|
|
@@ -82,6 +82,8 @@ public class Factory extends RubyObject {
|
|
82
82
|
|
83
83
|
@JRubyMethod(name = "register_type", required = 2, optional = 1)
|
84
84
|
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
|
85
|
+
testFrozen("MessagePack::Factory");
|
86
|
+
|
85
87
|
Ruby runtime = ctx.runtime;
|
86
88
|
IRubyObject type = args[0];
|
87
89
|
IRubyObject mod = args[1];
|
@@ -91,10 +93,6 @@ public class Factory extends RubyObject {
|
|
91
93
|
|
92
94
|
RubyHash options = null;
|
93
95
|
|
94
|
-
if (isFrozen()) {
|
95
|
-
throw runtime.newRuntimeError("can't modify frozen Factory");
|
96
|
-
}
|
97
|
-
|
98
96
|
if (args.length == 2) {
|
99
97
|
packerArg = runtime.newSymbol("to_msgpack_ext");
|
100
98
|
unpackerArg = runtime.newSymbol("from_msgpack_ext");
|
@@ -102,7 +100,13 @@ public class Factory extends RubyObject {
|
|
102
100
|
if (args[args.length - 1] instanceof RubyHash) {
|
103
101
|
options = (RubyHash) args[args.length - 1];
|
104
102
|
packerArg = options.fastARef(runtime.newSymbol("packer"));
|
103
|
+
if (packerArg != null && packerArg.isNil()) {
|
104
|
+
packerArg = null;
|
105
|
+
}
|
105
106
|
unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
|
107
|
+
if (unpackerArg != null && unpackerArg.isNil()) {
|
108
|
+
unpackerArg = null;
|
109
|
+
}
|
106
110
|
IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
|
107
111
|
if (optimizedSymbolsParsingArg != null && optimizedSymbolsParsingArg.isTrue()) {
|
108
112
|
throw runtime.newArgumentError("JRuby implementation does not support the optimized_symbols_parsing option");
|
@@ -149,7 +153,7 @@ public class Factory extends RubyObject {
|
|
149
153
|
|
150
154
|
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
|
151
155
|
|
152
|
-
if (extModule == runtime.getSymbol()) {
|
156
|
+
if (extModule == runtime.getSymbol() && !packerProc.isNil()) {
|
153
157
|
hasSymbolExtType = true;
|
154
158
|
}
|
155
159
|
|
@@ -28,12 +28,12 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
28
28
|
@JRubyClass(name="MessagePack::Packer")
|
29
29
|
public class Packer extends RubyObject {
|
30
30
|
private static final long serialVersionUID = 8451274621499362492L;
|
31
|
-
public ExtensionRegistry registry;
|
31
|
+
public transient ExtensionRegistry registry;
|
32
32
|
private Buffer buffer;
|
33
|
-
private Encoder encoder;
|
33
|
+
private transient Encoder encoder;
|
34
34
|
private boolean hasSymbolExtType;
|
35
35
|
private boolean hasBigintExtType;
|
36
|
-
private Encoding binaryEncoding;
|
36
|
+
private transient Encoding binaryEncoding;
|
37
37
|
|
38
38
|
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType, boolean hasBigintExtType) {
|
39
39
|
super(runtime, type);
|
@@ -95,6 +95,8 @@ public class Packer extends RubyObject {
|
|
95
95
|
|
96
96
|
@JRubyMethod(name = "register_type", required = 2, optional = 1)
|
97
97
|
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
|
98
|
+
testFrozen("MessagePack::Packer");
|
99
|
+
|
98
100
|
Ruby runtime = ctx.runtime;
|
99
101
|
IRubyObject type = args[0];
|
100
102
|
IRubyObject mod = args[1];
|
@@ -126,7 +128,7 @@ public class Packer extends RubyObject {
|
|
126
128
|
|
127
129
|
registry.put(extModule, (int) typeId, false, proc, arg, null, null);
|
128
130
|
|
129
|
-
if (extModule == runtime.getSymbol()) {
|
131
|
+
if (extModule == runtime.getSymbol() && !proc.isNil()) {
|
130
132
|
encoder.hasSymbolExtType = true;
|
131
133
|
}
|
132
134
|
|
@@ -21,18 +21,17 @@ import org.jruby.runtime.ThreadContext;
|
|
21
21
|
import org.jruby.anno.JRubyClass;
|
22
22
|
import org.jruby.anno.JRubyMethod;
|
23
23
|
import org.jruby.util.ByteList;
|
24
|
-
import org.jruby.ext.stringio.StringIO;
|
25
24
|
|
26
25
|
import static org.jruby.runtime.Visibility.PRIVATE;
|
27
26
|
|
28
27
|
@JRubyClass(name="MessagePack::Unpacker")
|
29
28
|
public class Unpacker extends RubyObject {
|
30
29
|
private static final long serialVersionUID = 8451264671199362492L;
|
31
|
-
private final ExtensionRegistry registry;
|
30
|
+
private transient final ExtensionRegistry registry;
|
32
31
|
|
33
|
-
private IRubyObject stream;
|
34
|
-
private IRubyObject data;
|
35
|
-
private Decoder decoder;
|
32
|
+
private transient IRubyObject stream;
|
33
|
+
private transient IRubyObject data;
|
34
|
+
private transient Decoder decoder;
|
36
35
|
private final RubyClass underflowErrorClass;
|
37
36
|
private boolean symbolizeKeys;
|
38
37
|
private boolean freeze;
|
@@ -129,6 +128,8 @@ public class Unpacker extends RubyObject {
|
|
129
128
|
|
130
129
|
@JRubyMethod(name = "register_type", required = 1, optional = 2)
|
131
130
|
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
|
131
|
+
testFrozen("MessagePack::Unpacker");
|
132
|
+
|
132
133
|
Ruby runtime = ctx.runtime;
|
133
134
|
IRubyObject type = args[0];
|
134
135
|
|
@@ -331,9 +332,7 @@ public class Unpacker extends RubyObject {
|
|
331
332
|
@JRubyMethod(name = "stream=", required = 1)
|
332
333
|
public IRubyObject setStream(ThreadContext ctx, IRubyObject stream) {
|
333
334
|
RubyString str;
|
334
|
-
if (stream instanceof
|
335
|
-
str = stream.callMethod(ctx, "string").asString();
|
336
|
-
} else if (stream instanceof RubyIO) {
|
335
|
+
if (stream instanceof RubyIO) {
|
337
336
|
str = stream.callMethod(ctx, "read").asString();
|
338
337
|
} else if (stream.respondsTo("read")) {
|
339
338
|
str = stream.callMethod(ctx, "read").asString();
|
data/ext/msgpack/buffer.c
CHANGED
@@ -19,10 +19,6 @@
|
|
19
19
|
#include "buffer.h"
|
20
20
|
#include "rmem.h"
|
21
21
|
|
22
|
-
#ifndef HAVE_RB_STR_REPLACE
|
23
|
-
static ID s_replace;
|
24
|
-
#endif
|
25
|
-
|
26
22
|
int msgpack_rb_encindex_utf8;
|
27
23
|
int msgpack_rb_encindex_usascii;
|
28
24
|
int msgpack_rb_encindex_ascii8bit;
|
@@ -40,10 +36,6 @@ void msgpack_buffer_static_init(void)
|
|
40
36
|
msgpack_rb_encindex_ascii8bit = rb_ascii8bit_encindex();
|
41
37
|
|
42
38
|
msgpack_rmem_init(&s_rmem);
|
43
|
-
|
44
|
-
#ifndef HAVE_RB_STR_REPLACE
|
45
|
-
s_replace = rb_intern("replace");
|
46
|
-
#endif
|
47
39
|
}
|
48
40
|
|
49
41
|
void msgpack_buffer_static_destroy(void)
|
@@ -66,7 +58,11 @@ void msgpack_buffer_init(msgpack_buffer_t* b)
|
|
66
58
|
static void _msgpack_buffer_chunk_destroy(msgpack_buffer_chunk_t* c)
|
67
59
|
{
|
68
60
|
if(c->mem != NULL) {
|
69
|
-
if(
|
61
|
+
if(c->rmem) {
|
62
|
+
if(!msgpack_rmem_free(&s_rmem, c->mem)) {
|
63
|
+
rb_bug("Failed to free an rmem pointer, memory leak?");
|
64
|
+
}
|
65
|
+
} else {
|
70
66
|
xfree(c->mem);
|
71
67
|
}
|
72
68
|
/* no needs to update rmem_owner because chunks will not be
|
@@ -330,14 +326,12 @@ static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE s
|
|
330
326
|
|
331
327
|
void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
332
328
|
{
|
333
|
-
size_t length = RSTRING_LEN(string);
|
334
|
-
|
335
329
|
if(b->io != Qnil) {
|
336
330
|
msgpack_buffer_flush(b);
|
337
331
|
if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
|
338
332
|
rb_funcall(b->io, b->io_write_all_method, 1, string);
|
339
333
|
} else {
|
340
|
-
msgpack_buffer_append(b, RSTRING_PTR(string),
|
334
|
+
msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string));
|
341
335
|
}
|
342
336
|
} else {
|
343
337
|
_msgpack_buffer_append_reference(b, string);
|
@@ -349,6 +343,8 @@ static inline void* _msgpack_buffer_chunk_malloc(
|
|
349
343
|
size_t required_size, size_t* allocated_size)
|
350
344
|
{
|
351
345
|
if(required_size <= MSGPACK_RMEM_PAGE_SIZE) {
|
346
|
+
c->rmem = true;
|
347
|
+
|
352
348
|
if((size_t)(b->rmem_end - b->rmem_last) < required_size) {
|
353
349
|
/* alloc new rmem page */
|
354
350
|
*allocated_size = MSGPACK_RMEM_PAGE_SIZE;
|
@@ -379,6 +375,7 @@ static inline void* _msgpack_buffer_chunk_malloc(
|
|
379
375
|
*allocated_size = required_size;
|
380
376
|
void* mem = xmalloc(required_size);
|
381
377
|
c->mem = mem;
|
378
|
+
c->rmem = false;
|
382
379
|
return mem;
|
383
380
|
}
|
384
381
|
|
data/ext/msgpack/buffer.h
CHANGED
@@ -78,6 +78,7 @@ struct msgpack_buffer_chunk_t {
|
|
78
78
|
void* mem;
|
79
79
|
msgpack_buffer_chunk_t* next;
|
80
80
|
VALUE mapped_string; /* RBString or NO_MAPPED_STRING */
|
81
|
+
bool rmem;
|
81
82
|
};
|
82
83
|
|
83
84
|
union msgpack_buffer_cast_block_t {
|
@@ -267,14 +268,7 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
|
|
267
268
|
static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
|
268
269
|
{
|
269
270
|
size_t length = RSTRING_LEN(string);
|
270
|
-
|
271
|
-
if(length > MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
|
272
|
-
_msgpack_buffer_append_long_string(b, string);
|
273
|
-
|
274
|
-
} else {
|
275
|
-
msgpack_buffer_append(b, RSTRING_PTR(string), length);
|
276
|
-
}
|
277
|
-
|
271
|
+
_msgpack_buffer_append_long_string(b, string);
|
278
272
|
return length;
|
279
273
|
}
|
280
274
|
|
@@ -479,7 +473,6 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
479
473
|
result = rb_str_new(b->read_buffer, length);
|
480
474
|
}
|
481
475
|
|
482
|
-
#if STR_UMINUS_DEDUPE
|
483
476
|
if (will_be_frozen) {
|
484
477
|
#if STR_UMINUS_DEDUPE_FROZEN
|
485
478
|
// Starting from MRI 2.8 it is preferable to freeze the string
|
@@ -491,7 +484,6 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
491
484
|
// frozen.
|
492
485
|
result = rb_funcall(result, s_uminus, 0);
|
493
486
|
}
|
494
|
-
#endif // STR_UMINUS_DEDUPE
|
495
487
|
_msgpack_buffer_consumed(b, length);
|
496
488
|
return result;
|
497
489
|
|
data/ext/msgpack/extconf.rb
CHANGED
@@ -5,15 +5,20 @@ have_header("st.h")
|
|
5
5
|
have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
|
6
6
|
have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
|
7
7
|
|
8
|
-
|
8
|
+
append_cflags([
|
9
|
+
"-fvisibility=hidden",
|
10
|
+
"-I..",
|
11
|
+
"-Wall",
|
12
|
+
"-O3",
|
13
|
+
"-std=gnu99"
|
14
|
+
])
|
15
|
+
append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
|
9
16
|
|
10
|
-
|
11
|
-
$CFLAGS << %[ -I.. -Wall -O3 #{RbConfig::CONFIG["debugflags"]} -std=gnu99]
|
12
|
-
end
|
17
|
+
append_cflags("-DRUBY_DEBUG=1") if ENV["MSGPACK_DEBUG"]
|
13
18
|
|
14
19
|
if RUBY_VERSION.start_with?('3.0.') && RUBY_VERSION <= '3.0.5'
|
15
20
|
# https://bugs.ruby-lang.org/issues/18772
|
16
|
-
|
21
|
+
append_cflags("-DRB_ENC_INTERNED_STR_NULL_CHECK=1")
|
17
22
|
end
|
18
23
|
|
19
24
|
# checking if Hash#[]= (rb_hash_aset) dedupes string keys (Ruby 2.6+)
|
@@ -23,35 +28,21 @@ r = rand.to_s
|
|
23
28
|
h[%W(#{r}).join('')] = :foo
|
24
29
|
x[%W(#{r}).join('')] = :foo
|
25
30
|
if x.keys[0].equal?(h.keys[0])
|
26
|
-
|
31
|
+
append_cflags("-DHASH_ASET_DEDUPE=1")
|
27
32
|
else
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
# checking if String#-@ (str_uminus) dedupes... ' (Ruby 2.5+)
|
33
|
-
begin
|
34
|
-
a = -(%w(t e s t).join)
|
35
|
-
b = -(%w(t e s t).join)
|
36
|
-
if a.equal?(b)
|
37
|
-
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
|
38
|
-
else
|
39
|
-
$CFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
|
40
|
-
end
|
41
|
-
rescue NoMethodError
|
42
|
-
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
|
33
|
+
append_cflags("-DHASH_ASET_DEDUPE=0")
|
43
34
|
end
|
44
35
|
|
45
36
|
# checking if String#-@ (str_uminus) directly interns frozen strings... ' (Ruby 3.0+)
|
46
37
|
begin
|
47
38
|
s = rand.to_s.freeze
|
48
39
|
if (-s).equal?(s) && (-s.dup).equal?(s)
|
49
|
-
|
40
|
+
append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=1")
|
50
41
|
else
|
51
|
-
|
42
|
+
append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=0")
|
52
43
|
end
|
53
44
|
rescue NoMethodError
|
54
|
-
|
45
|
+
append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=0")
|
55
46
|
end
|
56
47
|
|
57
48
|
if warnflags = CONFIG['warnflags']
|
data/ext/msgpack/factory_class.c
CHANGED
@@ -212,7 +212,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
212
212
|
VALUE packer_proc, unpacker_proc;
|
213
213
|
|
214
214
|
if (OBJ_FROZEN(self)) {
|
215
|
-
rb_raise(
|
215
|
+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
|
216
216
|
}
|
217
217
|
|
218
218
|
switch (argc) {
|
@@ -222,11 +222,12 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
222
222
|
unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
|
223
223
|
break;
|
224
224
|
case 3:
|
225
|
-
/* register_type(0x7f, Time, packer: proc-like,
|
225
|
+
/* register_type(0x7f, Time, packer: proc-like, unpacker: proc-like) */
|
226
226
|
options = argv[2];
|
227
227
|
if(rb_type(options) != T_HASH) {
|
228
228
|
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
229
229
|
}
|
230
|
+
|
230
231
|
packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
|
231
232
|
unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
|
232
233
|
break;
|
@@ -266,7 +267,9 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
266
267
|
}
|
267
268
|
|
268
269
|
if(ext_module == rb_cSymbol) {
|
269
|
-
|
270
|
+
if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
|
271
|
+
fc->has_symbol_ext_type = true;
|
272
|
+
}
|
270
273
|
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
271
274
|
fc->optimized_symbol_ext_type = true;
|
272
275
|
}
|
data/ext/msgpack/packer_class.c
CHANGED
@@ -233,7 +233,12 @@ static VALUE Packer_write_extension(VALUE self, VALUE obj)
|
|
233
233
|
msgpack_packer_t *pk = MessagePack_Packer_get(self);
|
234
234
|
Check_Type(obj, T_STRUCT);
|
235
235
|
|
236
|
-
|
236
|
+
VALUE rb_ext_type = RSTRUCT_GET(obj, 0);
|
237
|
+
if(!RB_TYPE_P(rb_ext_type, T_FIXNUM)) {
|
238
|
+
rb_raise(rb_eRangeError, "integer %s too big to convert to `signed char'", RSTRING_PTR(rb_String(rb_ext_type)));
|
239
|
+
}
|
240
|
+
|
241
|
+
int ext_type = FIX2INT(rb_ext_type);
|
237
242
|
if(ext_type < -128 || ext_type > 127) {
|
238
243
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
239
244
|
}
|
@@ -349,6 +354,10 @@ static VALUE Packer_registered_types_internal(VALUE self)
|
|
349
354
|
|
350
355
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
351
356
|
{
|
357
|
+
if (OBJ_FROZEN(self)) {
|
358
|
+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Packer");
|
359
|
+
}
|
360
|
+
|
352
361
|
msgpack_packer_t *pk = MessagePack_Packer_get(self);
|
353
362
|
|
354
363
|
int ext_type;
|
data/ext/msgpack/rmem.c
CHANGED
@@ -65,11 +65,10 @@ void* _msgpack_rmem_alloc2(msgpack_rmem_t* pm)
|
|
65
65
|
/* allocate new chunk */
|
66
66
|
c = pm->array_last++;
|
67
67
|
|
68
|
-
/* move to
|
69
|
-
|
70
|
-
pm->head = *c;
|
71
|
-
*c = tmp;
|
68
|
+
/* move head to array */
|
69
|
+
*c = pm->head;
|
72
70
|
|
71
|
+
pm->head.pages = NULL; /* make sure we don't point to another chunk's pages in case xmalloc triggers GC */
|
73
72
|
pm->head.mask = 0xffffffff & (~1); /* "& (~1)" means first chunk is already allocated */
|
74
73
|
pm->head.pages = xmalloc(MSGPACK_RMEM_PAGE_SIZE * 32);
|
75
74
|
|
data/ext/msgpack/unpacker.c
CHANGED
@@ -19,20 +19,14 @@
|
|
19
19
|
#include "unpacker.h"
|
20
20
|
#include "rmem.h"
|
21
21
|
#include "extension_value_class.h"
|
22
|
-
|
23
|
-
#if !defined(DISABLE_UNPACKER_STACK_RMEM) && \
|
24
|
-
MSGPACK_UNPACKER_STACK_CAPACITY * MSGPACK_UNPACKER_STACK_SIZE <= MSGPACK_RMEM_PAGE_SIZE
|
25
|
-
#define UNPACKER_STACK_RMEM
|
26
|
-
#endif
|
22
|
+
#include <assert.h>
|
27
23
|
|
28
24
|
static int RAW_TYPE_STRING = 256;
|
29
25
|
static int RAW_TYPE_BINARY = 257;
|
30
26
|
|
31
27
|
static ID s_call;
|
32
28
|
|
33
|
-
#ifdef UNPACKER_STACK_RMEM
|
34
29
|
static msgpack_rmem_t s_stack_rmem;
|
35
|
-
#endif
|
36
30
|
|
37
31
|
#if !defined(HAVE_RB_HASH_NEW_CAPA)
|
38
32
|
static inline VALUE rb_hash_new_capa(long capa)
|
@@ -43,18 +37,16 @@ static inline VALUE rb_hash_new_capa(long capa)
|
|
43
37
|
|
44
38
|
void msgpack_unpacker_static_init(void)
|
45
39
|
{
|
46
|
-
|
40
|
+
assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
|
41
|
+
|
47
42
|
msgpack_rmem_init(&s_stack_rmem);
|
48
|
-
#endif
|
49
43
|
|
50
44
|
s_call = rb_intern("call");
|
51
45
|
}
|
52
46
|
|
53
47
|
void msgpack_unpacker_static_destroy(void)
|
54
48
|
{
|
55
|
-
#ifdef UNPACKER_STACK_RMEM
|
56
49
|
msgpack_rmem_destroy(&s_stack_rmem);
|
57
|
-
#endif
|
58
50
|
}
|
59
51
|
|
60
52
|
#define HEAD_BYTE_REQUIRED 0xc1
|
@@ -62,13 +54,8 @@ void msgpack_unpacker_static_destroy(void)
|
|
62
54
|
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
63
55
|
msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
|
64
56
|
stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
65
|
-
#ifdef UNPACKER_STACK_RMEM
|
66
57
|
stack->data = msgpack_rmem_alloc(&s_stack_rmem);
|
67
58
|
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
68
|
-
#else
|
69
|
-
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
|
70
|
-
stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
|
71
|
-
#endif
|
72
59
|
return stack;
|
73
60
|
}
|
74
61
|
|
@@ -85,11 +72,9 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
85
72
|
}
|
86
73
|
|
87
74
|
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
xfree(stack->data);
|
92
|
-
#endif
|
75
|
+
if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
|
76
|
+
rb_bug("Failed to free an rmem pointer, memory leak?");
|
77
|
+
}
|
93
78
|
xfree(stack);
|
94
79
|
}
|
95
80
|
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -21,9 +21,7 @@
|
|
21
21
|
#include "buffer.h"
|
22
22
|
#include "unpacker_ext_registry.h"
|
23
23
|
|
24
|
-
#ifndef MSGPACK_UNPACKER_STACK_CAPACITY
|
25
24
|
#define MSGPACK_UNPACKER_STACK_CAPACITY 128
|
26
|
-
#endif
|
27
25
|
|
28
26
|
struct msgpack_unpacker_t;
|
29
27
|
typedef struct msgpack_unpacker_t msgpack_unpacker_t;
|
@@ -49,8 +47,6 @@ struct msgpack_unpacker_stack_t {
|
|
49
47
|
msgpack_unpacker_stack_t *parent;
|
50
48
|
};
|
51
49
|
|
52
|
-
#define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
|
53
|
-
|
54
50
|
struct msgpack_unpacker_t {
|
55
51
|
msgpack_buffer_t buffer;
|
56
52
|
msgpack_unpacker_stack_t *stack;
|
@@ -249,18 +249,6 @@ static VALUE Unpacker_read_map_header(VALUE self)
|
|
249
249
|
return ULONG2NUM(size); // long at least 32 bits
|
250
250
|
}
|
251
251
|
|
252
|
-
|
253
|
-
static VALUE Unpacker_feed(VALUE self, VALUE data)
|
254
|
-
{
|
255
|
-
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
256
|
-
|
257
|
-
StringValue(data);
|
258
|
-
|
259
|
-
msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), data);
|
260
|
-
|
261
|
-
return self;
|
262
|
-
}
|
263
|
-
|
264
252
|
static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
|
265
253
|
{
|
266
254
|
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
@@ -360,6 +348,10 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
|
|
360
348
|
|
361
349
|
static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
362
350
|
{
|
351
|
+
if (OBJ_FROZEN(self)) {
|
352
|
+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Unpacker");
|
353
|
+
}
|
354
|
+
|
363
355
|
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
364
356
|
|
365
357
|
int ext_type;
|
@@ -457,8 +449,8 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
457
449
|
rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
|
458
450
|
rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
|
459
451
|
rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
|
460
|
-
rb_define_method(cMessagePack_Unpacker, "feed",
|
461
|
-
|
452
|
+
rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed_reference, 1);
|
453
|
+
rb_define_alias(cMessagePack_Unpacker, "feed_reference", "feed");
|
462
454
|
rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
|
463
455
|
rb_define_method(cMessagePack_Unpacker, "feed_each", Unpacker_feed_each, 1);
|
464
456
|
rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 0);
|
data/lib/msgpack/factory.rb
CHANGED
@@ -88,33 +88,34 @@ module MessagePack
|
|
88
88
|
|
89
89
|
class Pool
|
90
90
|
if RUBY_ENGINE == "ruby"
|
91
|
-
class
|
91
|
+
class MemberPool
|
92
92
|
def initialize(size, &block)
|
93
93
|
@size = size
|
94
94
|
@new_member = block
|
95
95
|
@members = []
|
96
96
|
end
|
97
97
|
|
98
|
-
def
|
99
|
-
@members.pop || @new_member.call
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
98
|
+
def with
|
99
|
+
member = @members.pop || @new_member.call
|
100
|
+
begin
|
101
|
+
yield member
|
102
|
+
ensure
|
103
|
+
# If the pool is already full, we simply drop the extra member.
|
104
|
+
# This is because contrary to a connection pool, creating an extra instance
|
105
|
+
# is extremely unlikely to cause some kind of resource exhaustion.
|
106
|
+
#
|
107
|
+
# We could cycle the members (keep the newer one) but first It's more work and second
|
108
|
+
# the older member might have been created pre-fork, so it might be at least partially
|
109
|
+
# in shared memory.
|
110
|
+
if member && @members.size < @size
|
111
|
+
member.reset
|
112
|
+
@members << member
|
113
|
+
end
|
113
114
|
end
|
114
115
|
end
|
115
116
|
end
|
116
117
|
else
|
117
|
-
class
|
118
|
+
class MemberPool
|
118
119
|
def initialize(size, &block)
|
119
120
|
@size = size
|
120
121
|
@new_member = block
|
@@ -122,63 +123,50 @@ module MessagePack
|
|
122
123
|
@mutex = Mutex.new
|
123
124
|
end
|
124
125
|
|
125
|
-
def
|
126
|
-
@mutex.synchronize { @members.pop } || @new_member.call
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
member.
|
133
|
-
|
126
|
+
def with
|
127
|
+
member = @mutex.synchronize { @members.pop } || @new_member.call
|
128
|
+
begin
|
129
|
+
yield member
|
130
|
+
ensure
|
131
|
+
member.reset
|
132
|
+
@mutex.synchronize do
|
133
|
+
if member && @members.size < @size
|
134
|
+
@members << member
|
135
|
+
end
|
134
136
|
end
|
135
137
|
end
|
136
138
|
end
|
137
139
|
end
|
138
140
|
end
|
139
141
|
|
140
|
-
class PackerPool < AbstractPool
|
141
|
-
private
|
142
|
-
|
143
|
-
def reset(packer)
|
144
|
-
packer.clear
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
class UnpackerPool < AbstractPool
|
149
|
-
private
|
150
|
-
|
151
|
-
def reset(unpacker)
|
152
|
-
unpacker.reset
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
142
|
def initialize(factory, size, options = nil)
|
157
143
|
options = nil if !options || options.empty?
|
158
144
|
@factory = factory
|
159
|
-
@packers =
|
160
|
-
@unpackers =
|
145
|
+
@packers = MemberPool.new(size) { factory.packer(options).freeze }
|
146
|
+
@unpackers = MemberPool.new(size) { factory.unpacker(options).freeze }
|
161
147
|
end
|
162
148
|
|
163
149
|
def load(data)
|
164
|
-
|
165
|
-
|
166
|
-
unpacker.feed_reference(data)
|
150
|
+
@unpackers.with do |unpacker|
|
151
|
+
unpacker.feed(data)
|
167
152
|
unpacker.full_unpack
|
168
|
-
ensure
|
169
|
-
@unpackers.checkin(unpacker)
|
170
153
|
end
|
171
154
|
end
|
172
155
|
|
173
156
|
def dump(object)
|
174
|
-
|
175
|
-
begin
|
157
|
+
@packers.with do |packer|
|
176
158
|
packer.write(object)
|
177
159
|
packer.full_pack
|
178
|
-
ensure
|
179
|
-
@packers.checkin(packer)
|
180
160
|
end
|
181
161
|
end
|
162
|
+
|
163
|
+
def unpacker(&block)
|
164
|
+
@unpackers.with(&block)
|
165
|
+
end
|
166
|
+
|
167
|
+
def packer(&block)
|
168
|
+
@packers.with(&block)
|
169
|
+
end
|
182
170
|
end
|
183
171
|
end
|
184
172
|
end
|
data/lib/msgpack/version.rb
CHANGED
data/msgpack.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: msgpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-05-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -201,14 +201,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
201
201
|
requirements:
|
202
202
|
- - ">="
|
203
203
|
- !ruby/object:Gem::Version
|
204
|
-
version: '2.
|
204
|
+
version: '2.5'
|
205
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
206
206
|
requirements:
|
207
207
|
- - ">="
|
208
208
|
- !ruby/object:Gem::Version
|
209
209
|
version: '0'
|
210
210
|
requirements: []
|
211
|
-
rubygems_version: 3.
|
211
|
+
rubygems_version: 3.1.2
|
212
212
|
signing_key:
|
213
213
|
specification_version: 4
|
214
214
|
summary: MessagePack, a binary-based efficient data interchange format.
|