Skip to content

Commit 1164b40

Browse files
committed
2 parents c09121f + c30c227 commit 1164b40

4 files changed

Lines changed: 161 additions & 52 deletions

File tree

build_config.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
conf.cc.flags << '-fno-omit-frame-pointer'
66
# conf.enable_debug
77
conf.enable_test
8-
conf.gembox 'full-core'
8+
conf.gembox 'default'
99
conf.gem File.expand_path(File.dirname(__FILE__))
1010
end

src/mrb_msgpack.cpp

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
// mruby-simplemsgpack C++ packer wrapper (msgpack::packer + msgpack::sbuffer)
21
#define MSGPACK_NO_BOOST
32
#define MSGPACK_DEFAULT_API_VERSION 3
43
#include <msgpack.hpp>
5-
extern "C" {
4+
65
#include <mruby.h>
76
#include <mruby/array.h>
87
#include <mruby/class.h>
@@ -14,9 +13,10 @@ extern "C" {
1413
#include <mruby/string_is_utf8.h>
1514
#include <mruby/presym.h>
1615
#include <mruby/msgpack.h>
16+
MRB_BEGIN_DECL
1717
#include <mruby/internal.h>
18+
MRB_END_DECL
1819
#include <mruby/gc.h>
19-
}
2020
#include <mruby/cpp_helpers.hpp>
2121
#include <mruby/num_helpers.hpp>
2222
#include <string>
@@ -69,6 +69,37 @@ static inline void mrb_msgpack_pack_string_value(mrb_state *mrb, mrb_value self,
6969
}
7070
}
7171

72+
#ifdef MRB_MSGPACK_SYMBOLS
73+
74+
#ifndef MRB_MSGPACK_SYMBOLS_EXT
75+
#define MRB_MSGPACK_SYMBOLS_EXT 0
76+
#endif
77+
78+
template <typename Packer>
79+
static inline void
80+
mrb_msgpack_pack_symbol_value(mrb_state* mrb, mrb_value self, Packer& pk)
81+
{
82+
mrb_sym sym = mrb_symbol(self);
83+
84+
#ifdef MRB_MSGPACK_SYMBOLS_AS_INT
85+
// Pack the raw mrb_sym value as the ext body
86+
pk.pack_ext(sizeof(sym), static_cast<int8_t>(MRB_MSGPACK_SYMBOLS_EXT));
87+
pk.pack_ext_body(reinterpret_cast<const char*>(&sym), sizeof(sym));
88+
89+
#else
90+
// Pack the symbol’s name as the ext body, using mrb_sym_name_len
91+
mrb_int len;
92+
const char* name = mrb_sym_name_len(mrb, sym, &len);
93+
94+
pk.pack_ext(static_cast<uint32_t>(len),
95+
static_cast<int8_t>(MRB_MSGPACK_SYMBOLS_EXT));
96+
pk.pack_ext_body(name, static_cast<size_t>(len));
97+
98+
#endif
99+
}
100+
101+
#endif // MRB_MSGPACK_SYMBOLS
102+
72103
template <typename Packer>
73104
static void mrb_msgpack_pack_array_value(mrb_state* mrb, mrb_value self, Packer& pk) {
74105
mrb_int n = RARRAY_LEN(self);
@@ -226,6 +257,11 @@ static void mrb_msgpack_pack_value(mrb_state* mrb, mrb_value self, Packer& pk) {
226257
case MRB_TT_STRING:
227258
mrb_msgpack_pack_string_value(mrb, self, pk);
228259
break;
260+
#ifdef MRB_MSGPACK_SYMBOLS
261+
case MRB_TT_SYMBOL:
262+
mrb_msgpack_pack_symbol_value(mrb, self, pk);
263+
break;
264+
#endif
229265
default: {
230266
if (mrb_msgpack_pack_ext_value(mrb, self, pk)) break;
231267

@@ -359,6 +395,13 @@ mrb_msgpack_register_pack_type(mrb_state* mrb, mrb_value self)
359395
mrb_raise(mrb, E_TYPE_ERROR, "not a block");
360396
}
361397

398+
#ifdef MRB_MSGPACK_SYMBOLS
399+
// Prevent registering ext packers for Symbol when built-in symbol packing is enabled
400+
if (mrb_class_ptr(mrb_class) == mrb->symbol_class) {
401+
mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot register ext packer for Symbol when MRB_MSGPACK_SYMBOLS is enabled");
402+
}
403+
#endif
404+
362405
ext_packers = mrb_const_get(mrb, self, MRB_SYM(_ExtPackers));
363406
ext_config = mrb_hash_new_capa(mrb, 2);
364407
mrb_hash_set(mrb, ext_config, mrb_symbol_value(MRB_SYM(type)), mrb_int_value(mrb, type));
@@ -409,8 +452,26 @@ mrb_unpack_msgpack_obj(mrb_state* mrb, const msgpack::object& obj)
409452
case msgpack::type::MAP:
410453
return mrb_unpack_msgpack_obj_map(mrb, obj);
411454
case msgpack::type::EXT: {
412-
mrb_value ext_type = mrb_int_value(mrb, obj.via.ext.type());
413-
455+
auto ext_type = mrb_convert_number(mrb, obj.via.ext.type());
456+
#ifdef MRB_MSGPACK_SYMBOLS
457+
if (ext_type == MRB_MSGPACK_SYMBOLS_EXT) {
458+
# ifdef MRB_MSGPACK_SYMBOLS_AS_INT
459+
// Body is a raw mrb_sym
460+
if (unlikely(obj.via.ext.size != sizeof(mrb_sym))) {
461+
mrb_raise(mrb, E_MSGPACK_ERROR, "invalid symbol ext body size");
462+
}
463+
mrb_sym sym;
464+
std::memcpy(&sym, obj.via.ext.data(), sizeof(sym));
465+
return mrb_symbol_value(sym);
466+
# else
467+
// Body is the UTF‑8 symbol name
468+
return mrb_symbol_value(
469+
mrb_intern(mrb,
470+
obj.via.ext.data(),
471+
(size_t)obj.via.ext.size));
472+
# endif
473+
}
474+
#endif // MRB_MSGPACK_SYMBOLS
414475
mrb_value unpacker = mrb_hash_get(mrb,
415476
mrb_const_get(mrb, mrb_obj_value(mrb_module_get_id(mrb, MRB_SYM(MessagePack))), MRB_SYM(_ExtUnpackers)), ext_type);
416477
if (likely(mrb_type(unpacker) == MRB_TT_PROC)) {
@@ -666,6 +727,14 @@ mrb_msgpack_register_unpack_type(mrb_state* mrb, mrb_value self)
666727
mrb_raise(mrb, E_TYPE_ERROR, "not a block");
667728
}
668729

730+
#ifdef MRB_MSGPACK_SYMBOLS
731+
/* Prevent registering an unpacker for the reserved symbol ext type */
732+
if (type == MRB_MSGPACK_SYMBOLS_EXT) {
733+
mrb_raise(mrb, E_ARGUMENT_ERROR,
734+
"cannot register unpacker for Symbol ext type when MRB_MSGPACK_SYMBOLS is enabled");
735+
}
736+
#endif
737+
669738
mrb_hash_set(mrb, mrb_const_get(mrb, self, MRB_SYM(_ExtUnpackers)), mrb_int_value(mrb, type), block);
670739

671740
return mrb_nil_value();
@@ -778,4 +847,4 @@ mrb_mruby_simplemsgpack_gem_init(mrb_state* mrb)
778847

779848

780849
void mrb_mruby_simplemsgpack_gem_final(mrb_state* mrb) {}
781-
MRB_END_DECL
850+
MRB_END_DECL

test/msgpack.cpp

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <mruby.h>
12
#include <mruby/msgpack.h>
23
#include <limits.h>
34
#include <mruby/num_helpers.hpp>
@@ -13,7 +14,6 @@ mrb_msgpack_test_unpack(mrb_state *mrb, mrb_value self)
1314
{
1415
mrb_value hallo;
1516
mrb_get_args(mrb, "S", &hallo);
16-
1717
return mrb_msgpack_unpack(mrb, hallo);
1818
}
1919

@@ -22,18 +22,55 @@ void
2222
mrb_mruby_simplemsgpack_gem_test(mrb_state *mrb)
2323
{
2424
struct RClass *msgpack_test = mrb_define_module(mrb, "MessagePackTest");
25-
mrb_define_module_function(mrb, msgpack_test, "test_pack", mrb_msgpack_test_pack, MRB_ARGS_NONE());
26-
mrb_define_module_function(mrb, msgpack_test, "test_unpack", mrb_msgpack_test_unpack, MRB_ARGS_REQ(1));
27-
mrb_define_const(mrb, msgpack_test, "FIXNUM_MAX", mrb_convert_number(mrb, MRB_INT_MAX));
28-
mrb_define_const(mrb, msgpack_test, "FIXNUM_MIN", mrb_convert_number(mrb, MRB_INT_MIN));
29-
#ifndef MRB_WITHOUT_FLOAT
30-
#ifdef MRB_USE_FLOAT
31-
mrb_define_const(mrb, msgpack_test, "FLOAT_MAX", mrb_float_value(mrb, FLT_MAX));
32-
mrb_define_const(mrb, msgpack_test, "FLOAT_MIN", mrb_float_value(mrb, FLT_MIN));
25+
26+
mrb_define_module_function(mrb, msgpack_test, "test_pack",
27+
mrb_msgpack_test_pack, MRB_ARGS_NONE());
28+
mrb_define_module_function(mrb, msgpack_test, "test_unpack",
29+
mrb_msgpack_test_unpack, MRB_ARGS_REQ(1));
30+
31+
mrb_define_const(mrb, msgpack_test, "FIXNUM_MAX",
32+
mrb_int_value(mrb, MRB_INT_MAX));
33+
mrb_define_const(mrb, msgpack_test, "FIXNUM_MIN",
34+
mrb_int_value(mrb, MRB_INT_MIN));
35+
36+
#ifdef MRB_MSGPACK_SYMBOLS
37+
#ifndef MRB_MSGPACK_SYMBOLS_EXT
38+
#define MRB_MSGPACK_SYMBOLS_EXT 0
39+
#endif
40+
mrb_define_const(mrb, msgpack_test,
41+
"SYMBOLS_ENABLED",
42+
mrb_true_value());
43+
mrb_define_const(mrb, msgpack_test,
44+
"SYMBOLS_EXT_TYPE",
45+
mrb_int_value(mrb, MRB_MSGPACK_SYMBOLS_EXT));
46+
47+
# ifdef MRB_MSGPACK_SYMBOLS_AS_INT
48+
mrb_define_const(mrb, msgpack_test,
49+
"SYMBOLS_MODE",
50+
mrb_str_new_lit(mrb, "int"));
51+
# else
52+
mrb_define_const(mrb, msgpack_test,
53+
"SYMBOLS_MODE",
54+
mrb_str_new_lit(mrb, "string"));
55+
# endif
3356
#else
34-
mrb_define_const(mrb, msgpack_test, "FLOAT_MAX", mrb_float_value(mrb, DBL_MAX));
35-
mrb_define_const(mrb, msgpack_test, "FLOAT_MIN", mrb_float_value(mrb, DBL_MIN));
57+
mrb_define_const(mrb, msgpack_test,
58+
"SYMBOLS_ENABLED",
59+
mrb_false_value());
3660
#endif
61+
62+
#ifndef MRB_WITHOUT_FLOAT
63+
# ifdef MRB_USE_FLOAT
64+
mrb_define_const(mrb, msgpack_test, "FLOAT_MAX",
65+
mrb_float_value(mrb, FLT_MAX));
66+
mrb_define_const(mrb, msgpack_test, "FLOAT_MIN",
67+
mrb_float_value(mrb, FLT_MIN));
68+
# else
69+
mrb_define_const(mrb, msgpack_test, "FLOAT_MAX",
70+
mrb_float_value(mrb, DBL_MAX));
71+
mrb_define_const(mrb, msgpack_test, "FLOAT_MIN",
72+
mrb_float_value(mrb, DBL_MIN));
73+
# endif
3774
#endif
3875
}
3976
MRB_END_DECL

test/msgpack.rb

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,26 @@
3535
assert_equal("😎", MessagePack.unpack("😎".to_msgpack))
3636
end
3737

38-
assert("Symbol#to_msgpack") do
39-
assert_equal('symbol', MessagePack.unpack(:symbol.to_msgpack))
40-
assert_equal('symbol', MessagePack.unpack(MessagePack.pack(:symbol)))
38+
if MessagePackTest::SYMBOLS_ENABLED
39+
assert("Symbol#to_msgpack MRB_MSGPACK_SYMBOLS") do
40+
assert_equal(:symbol, MessagePack.unpack(:symbol.to_msgpack))
41+
assert_equal(:symbol, MessagePack.unpack(MessagePack.pack(:symbol)))
42+
end
43+
else
44+
assert("Symbol#to_msgpack") do
45+
assert_equal('symbol', MessagePack.unpack(:symbol.to_msgpack))
46+
assert_equal('symbol', MessagePack.unpack(MessagePack.pack(:symbol)))
47+
end
48+
49+
assert("Symbol#to_msgpack with registered ext type") do
50+
MessagePack.register_pack_type(0, Symbol) { |symbol| symbol.to_s }
51+
MessagePack.register_unpack_type(0) { |data| data.to_sym }
52+
assert_equal(:symbol, MessagePack.unpack(:symbol.to_msgpack))
53+
54+
hash = { key: 123, nested: [:array] }
55+
assert_equal(hash, MessagePack.unpack(hash.to_msgpack))
56+
assert_equal(hash, MessagePack.unpack(MessagePack.pack(hash)))
57+
end
4158
end
4259

4360
assert("Array#to_msgpack") do
@@ -98,20 +115,22 @@
98115
assert_equal(unpacked, [value1, value2, value3])
99116
end
100117

118+
class TestClassFoo; end
119+
101120
assert("MessagePack.register_pack_type") do
102121
assert_raise(RangeError, "ext type out of range") do
103-
MessagePack.register_pack_type(-1, Symbol)
122+
MessagePack.register_pack_type(-1, TestClassFoo)
104123
end
105124

106125
assert_raise(RangeError, "ext type out of range") do
107-
MessagePack.register_pack_type(128, Symbol)
126+
MessagePack.register_pack_type(128, TestClassFoo)
108127
end
109128

110129
assert_raise(ArgumentError, "no block given") do
111-
MessagePack.register_pack_type(1, Symbol)
130+
MessagePack.register_pack_type(127, TestClassFoo)
112131
end
113132

114-
assert_nil(MessagePack.register_pack_type(1, Symbol) {})
133+
assert_nil(MessagePack.register_pack_type(127, TestClassFoo) {})
115134
end
116135

117136
assert("MessagePack.register_unpack_type") do
@@ -124,40 +143,24 @@
124143
end
125144

126145
assert_raise(ArgumentError, "no block given") do
127-
MessagePack.register_unpack_type(1)
146+
MessagePack.register_unpack_type(127)
128147
end
129148

130-
assert_nil(MessagePack.register_unpack_type(1) {})
131-
end
132-
133-
assert("Symbol#to_msgpack with registered ext type") do
134-
MessagePack.register_pack_type(0, Symbol) { |symbol| symbol.to_s }
135-
MessagePack.register_unpack_type(0) { |data| data.to_sym }
136-
assert_equal(:symbol, MessagePack.unpack(:symbol.to_msgpack))
137-
138-
hash = { key: 123, nested: [:array] }
139-
assert_equal(hash, MessagePack.unpack(hash.to_msgpack))
140-
assert_equal(hash, MessagePack.unpack(MessagePack.pack(hash)))
149+
assert_nil(MessagePack.register_unpack_type(127) {})
141150
end
142151

143152
assert("Class#to_msgpack with registered ext type") do
144-
MessagePack.register_pack_type(0, Class) { |mod| mod.to_s }
145-
MessagePack.register_unpack_type(0) { |data| data.constantize }
153+
MessagePack.register_pack_type(1, Class) { |mod| mod.to_s }
154+
MessagePack.register_unpack_type(1) { |data| data.constantize }
146155
assert_equal(MessagePack::Error, MessagePack.unpack(MessagePack::Error.to_msgpack))
147156
end
148157

149158
assert("Registered ext type for one of the core types is ignored") do
150-
MessagePack.register_pack_type(0, Array) { |array| nil }
151-
MessagePack.register_unpack_type(0) { |data| nil }
159+
MessagePack.register_pack_type(1, Array) { |array| nil }
160+
MessagePack.register_unpack_type(1) { |data| nil }
152161
assert_equal(['item'], MessagePack.unpack(['item'].to_msgpack))
153162
end
154163

155-
assert("Unknown Ext Type raises a Exception when tried to unpack") do
156-
assert_raise(MessagePack::Error) do
157-
MessagePack.register_pack_type(50, Symbol) { |symbol| symbol.to_s }
158-
MessagePack.unpack(:hallo.to_msgpack)
159-
end
160-
end
161164

162165
assert("Extension types are inherited") do
163166
class Test
@@ -174,8 +177,8 @@ def ==(other)
174177

175178
class InheritsTest < Test; end
176179

177-
MessagePack.register_pack_type(0, Test) { |test| test.class.to_s + '#' + test.id }
178-
MessagePack.register_unpack_type(0) do |data|
180+
MessagePack.register_pack_type(1, Test) { |test| test.class.to_s + '#' + test.id }
181+
MessagePack.register_unpack_type(1) do |data|
179182
class_name, id = data.split('#')
180183
class_name.constantize.new(id)
181184
end
@@ -186,12 +189,12 @@ class InheritsTest < Test; end
186189

187190
assert("Extension types for modules") do
188191
module Mod; end
189-
MessagePack.register_pack_type(0, Mod) { |obj| 'packed' }
192+
MessagePack.register_pack_type(1, Mod) { |obj| 'packed' }
190193

191194
class Cls; include Mod end
192-
assert_equal(Cls.new.to_msgpack, "\xc7\x06\x00packed")
195+
assert_equal(Cls.new.to_msgpack, "\xc7\x06\x01packed")
193196

194-
assert_equal(Object.new.extend(Mod).to_msgpack, "\xc7\x06\x00packed")
197+
assert_equal(Object.new.extend(Mod).to_msgpack, "\xc7\x06\x01packed")
195198
end
196199

197200
assert("C Packing and unpacking") do

0 commit comments

Comments
 (0)