From c6a1f7372d19418004c2c86403c90ff88a6c77c4 Mon Sep 17 00:00:00 2001 From: John Brophy Date: Thu, 31 May 2018 15:56:22 +0100 Subject: [PATCH] fix issue #38 - decode negative int32 --- pb/standard/unpack.lua | 19 +++++++++++++++++++ protos/int32.proto | 4 ++++ tests/test_negative_int32.lua | 13 +++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 protos/int32.proto create mode 100644 tests/test_negative_int32.lua diff --git a/pb/standard/unpack.lua b/pb/standard/unpack.lua index 9f5840e..6b80446 100644 --- a/pb/standard/unpack.lua +++ b/pb/standard/unpack.lua @@ -116,10 +116,26 @@ local function unpack_varint64(data, off, max_off, signed) return num, off + 1 end +local function unpack_neg_varint32(data, off, max_off) + local boff = 1 + local num = 0 + local bits35 = 34359738368 -- 2^(5*7) + for i = 1, 5 do + num = num + (band(data:byte(off), 0x7F) * boff) + off = off + 1 + boff = boff * 128 + end + while data:byte(off) >= 128 do + off = off + 1 + end + return num - bits35, off + 1 +end + local function unpack_varint32(data, off, max_off) local b = data:byte(off) local num = band(b, 0x7F) local boff = 128 + local start_off = off while b >= 128 do off = off + 1 if off > max_off then @@ -129,6 +145,9 @@ local function unpack_varint32(data, off, max_off) num = num + (band(b, 0x7F) * boff) boff = boff * 128 end + if off - start_off + 1 == 10 then + return unpack_neg_varint32(data, start_off, max_off) + end return num, off + 1 end diff --git a/protos/int32.proto b/protos/int32.proto new file mode 100644 index 0000000..4897f07 --- /dev/null +++ b/protos/int32.proto @@ -0,0 +1,4 @@ +message TestInt32 +{ + optional int32 int32_ = 1; +} \ No newline at end of file diff --git a/tests/test_negative_int32.lua b/tests/test_negative_int32.lua new file mode 100644 index 0000000..fc116f7 --- /dev/null +++ b/tests/test_negative_int32.lua @@ -0,0 +1,13 @@ +local pb = require"pb" +local value = -1 +local integer32 = require"protos.int32" + +local msg = integer32.TestInt32() +msg.int32_ = value; +binary,err = msg:Serialize(); +assert(not err) + +local decoded = integer32.TestInt32():Parse(binary) +assert(decoded:IsInitialized()) +assert(decoded:HasField('int32_')) +assert(value == decoded.int32_) \ No newline at end of file