Skip to content

Commit 32510e0

Browse files
committed
Merge pull request #24 from technorama/master
add symbolize_keys support to unpack (compatible with msgpack-jruby)
2 parents dfb57de + 1efc8c0 commit 32510e0

6 files changed

Lines changed: 43 additions & 7 deletions

File tree

ext/msgpack/buffer.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct msgpack_buffer_t {
108108
size_t write_reference_threshold;
109109
size_t read_reference_threshold;
110110
size_t io_buffer_size;
111+
bool symbolize_keys;
111112

112113
VALUE owner;
113114
};
@@ -156,6 +157,11 @@ static inline void msgpack_buffer_reset_io(msgpack_buffer_t* b)
156157
b->io = Qnil;
157158
}
158159

160+
static inline void msgpack_buffer_set_symbolize_keys(msgpack_buffer_t* b, bool val)
161+
{
162+
b->symbolize_keys = val;
163+
}
164+
159165
static inline bool msgpack_buffer_has_io(msgpack_buffer_t* b)
160166
{
161167
return b->io != Qnil;
@@ -418,8 +424,14 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
418424
return rb_str_substr(b->head->mapped_string, offset, length);
419425
}
420426

421-
static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen)
427+
static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen, bool symbolize_keys)
422428
{
429+
if(symbolize_keys) {
430+
VALUE result = ID2SYM(rb_intern2(b->read_buffer, length));
431+
_msgpack_buffer_consumed(b, length);
432+
return result;
433+
}
434+
423435
#ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
424436
/* optimize */
425437
if(!will_be_frozen &&

ext/msgpack/buffer_class.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ void MessagePack_Buffer_initialize(msgpack_buffer_t* b, VALUE io, VALUE options)
105105
if(v != Qnil) {
106106
msgpack_buffer_set_io_buffer_size(b, NUM2ULONG(v));
107107
}
108+
109+
v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
110+
if(v != Qnil) {
111+
msgpack_buffer_set_symbolize_keys(b, RTEST(v));
112+
}
108113
}
109114
}
110115

ext/msgpack/unpacker.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,15 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, bool str)
257257
/* don't use zerocopy for hash keys but get a frozen string directly
258258
* because rb_hash_aset freezes keys and it causes copying */
259259
bool will_freeze = is_reading_map_key(uk);
260-
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze);
261-
object_complete_string(uk, string);
262-
if(will_freeze) {
263-
rb_obj_freeze(string);
260+
bool symbolize_keys = will_freeze && UNPACKER_BUFFER_(uk)->symbolize_keys;
261+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, symbolize_keys);
262+
if(symbolize_keys) {
263+
object_complete(uk, string);
264+
} else {
265+
object_complete_string(uk, string);
266+
if(will_freeze) {
267+
rb_obj_freeze(string);
268+
}
264269
}
265270
uk->reading_raw_remaining = 0;
266271
return PRIMITIVE_OBJECT_COMPLETE;

ext/msgpack/unpacker_class.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,16 @@ static VALUE Unpacker_reset(VALUE self)
288288
VALUE MessagePack_unpack(int argc, VALUE* argv)
289289
{
290290
VALUE src;
291+
VALUE options = Qnil;
291292

292293
switch(argc) {
293294
case 1:
294295
src = argv[0];
295296
break;
297+
case 2:
298+
src = argv[0];
299+
options = argv[1];
300+
break;
296301
default:
297302
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
298303
}
@@ -312,11 +317,12 @@ VALUE MessagePack_unpack(int argc, VALUE* argv)
312317
msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(uk), 0);
313318

314319
if(io != Qnil) {
315-
MessagePack_Buffer_initialize(UNPACKER_BUFFER_(uk), io, Qnil);
320+
MessagePack_Buffer_initialize(UNPACKER_BUFFER_(uk), io, options);
316321
}
317322

318323
if(src != Qnil) {
319324
/* prefer reference than copying; see MessagePack_Unpacker_module_init */
325+
MessagePack_Buffer_initialize(UNPACKER_BUFFER_(uk), io, options);
320326
msgpack_buffer_append_string(UNPACKER_BUFFER_(uk), src);
321327
}
322328

spec/buffer_io_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def set_source(s)
201201
fragments.each {|s|
202202
lambda {
203203
b.skip_all(s.size)
204-
}.should_not raise_error(EOFError)
204+
}.should_not raise_error
205205
}
206206
b.empty?.should == true
207207
lambda {

spec/unpacker_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@
230230
parsed.should == true
231231
end
232232

233+
it 'symbolize_keys' do
234+
hash = { a: :b, c: :d }
235+
hash_result = { a: 'b', c: 'd' }
236+
MessagePack.unpack(MessagePack.pack(hash), symbolize_keys: true).should == hash_result
237+
hash = { 'a' => 'b', 'c' => 'd' }
238+
MessagePack.unpack(MessagePack.pack(hash), symbolize_keys: true).should == hash_result
239+
end
240+
233241
it "msgpack str 8 type" do
234242
MessagePack.unpack([0xd9, 0x00].pack('C*')).should == ""
235243
MessagePack.unpack([0xd9, 0x01].pack('C*') + 'a').should == "a"

0 commit comments

Comments
 (0)