ruby: fixese backward compatibility of streaming deserializer

This commit is contained in:
frsyuki 2010-04-23 18:13:36 +09:00
parent 60fbaf7612
commit b10a736744
2 changed files with 48 additions and 8 deletions

View File

@ -218,6 +218,28 @@ class MessagePackTestFormat < Test::Unit::TestCase
assert_equal(parsed, 1) assert_equal(parsed, 1)
end end
it "streaming backward compatibility" do
obj = [{["a","b"]=>["c","d"]}, ["e","f"], "d"]
pac = MessagePack::Unpacker.new
buffer = ""
nread = 0
parsed = 0
obj.to_msgpack.split(//).each do |b|
buffer << b
nread = pac.execute(buffer, nread)
if pac.finished?
o = pac.data
assert_equal(obj, o)
parsed += 1
pac.reset
buffer.slice!(0, nread)
nread = 0
next unless buffer.empty?
end
end
assert_equal(parsed, 1)
end
private private
def check(len, obj) def check(len, obj)
v = obj.to_msgpack v = obj.to_msgpack

View File

@ -389,25 +389,43 @@ static VALUE MessagePack_unpack(VALUE self, VALUE data)
} }
static VALUE MessagePack_Unpacker_execute_impl(VALUE self, VALUE data,
size_t from, size_t limit)
{
UNPACKER(self, mp);
if(from >= limit) {
rb_raise(eUnpackError, "offset is bigger than data buffer size.");
}
int ret = template_execute_wrap(mp, data, limit, &from);
if(ret < 0) {
rb_raise(eUnpackError, "parse error.");
} else if(ret > 0) {
mp->user.finished = 1;
return ULONG2NUM(from);
} else {
mp->user.finished = 0;
return ULONG2NUM(from);
}
}
/* compat */ /* compat */
static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data, static VALUE MessagePack_Unpacker_execute_limit(VALUE self, VALUE data,
VALUE off, VALUE limit) VALUE off, VALUE limit)
{ {
CHECK_STRING_TYPE(data); CHECK_STRING_TYPE(data);
UNPACKER(self, mp); return MessagePack_Unpacker_execute_impl(self, data,
size_t from = (size_t)NUM2ULONG(off); (size_t)NUM2ULONG(off), (size_t)NUM2ULONG(limit));
int ret = template_execute_wrap(mp, data, NUM2ULONG(limit), &from);
return INT2FIX(ret);
} }
/* compat */ /* compat */
static VALUE MessagePack_Unpacker_execute(VALUE self, VALUE data, VALUE off) static VALUE MessagePack_Unpacker_execute(VALUE self, VALUE data, VALUE off)
{ {
CHECK_STRING_TYPE(data); CHECK_STRING_TYPE(data);
UNPACKER(self, mp); return MessagePack_Unpacker_execute_impl(self, data,
size_t from = (size_t)NUM2ULONG(off); (size_t)NUM2ULONG(off), (size_t)RSTRING_LEN(data));
int ret = template_execute_wrap(mp, data, RSTRING_LEN(data), &from);
return INT2FIX(ret);
} }
/* compat */ /* compat */