Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions lua/qjson/table.lua
Original file line number Diff line number Diff line change
Expand Up @@ -573,9 +573,7 @@ end

local function encode_cdata(v)
if ffi.istype(int64_ct, v) or ffi.istype(uint64_ct, v) then
local s = tostring(v)
s = s:gsub("ULL$", "")
s = s:gsub("LL$", "")
local s = tostring(v):gsub("[UuLl]+$", "")
return s
end
error("qjson.encode: unsupported value type: cdata")
Expand Down
35 changes: 35 additions & 0 deletions tests/lua/encode_errors_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,55 @@ describe("qjson.encode error coverage", function()
assert_encode_error(coroutine.create(function() end), "qjson.encode: unsupported value type: thread")
assert_encode_error(newproxy(false), "qjson.encode: unsupported value type: userdata")
assert_encode_error(ffi.new("double", 1.25), "qjson.encode: unsupported value type: cdata")
assert_encode_error(ffi.new("struct { int x; }"), "qjson.encode: unsupported value type: cdata")
assert_encode_error(ffi.cast("void *", 1), "qjson.encode: unsupported value type: cdata")
end)

it("encodes int64 and uint64 cdata as decimal JSON integers", function()
assert.are.equal("9007199254740993", qjson.encode(9007199254740993LL))
assert.are.equal("18446744073709551615", qjson.encode(18446744073709551615ULL))
assert.are.equal(1, select("#", qjson.encode(9007199254740993LL)))
assert.are.equal(1, select("#", qjson.encode(18446744073709551615ULL)))
assert.are.equal('{"i":9007199254740993}', qjson.encode({ i = 9007199254740993LL }))
assert.are.equal('{"u":18446744073709551615}', qjson.encode({ u = 18446744073709551615ULL }))
end)

it("encodes 64-bit cdata boundary values without precision loss", function()
assert.are.equal("9223372036854775807", qjson.encode(9223372036854775807LL))
assert.are.equal("-9223372036854775808", qjson.encode(ffi.new("int64_t", -9223372036854775807LL - 1LL)))
assert.are.equal("18446744073709551615", qjson.encode(18446744073709551615ULL))
assert.are.equal("0", qjson.encode(0LL))
assert.are.equal("0", qjson.encode(0ULL))
end)

it("encodes nested int64 and uint64 cdata values", function()
assert.are.equal("[1,2]", qjson.encode({ 1LL, 2LL }))
assert.are.equal('[{"x":9007199254740993},{"y":18446744073709551615}]', qjson.encode({
{ x = 9007199254740993LL },
{ y = 18446744073709551615ULL },
}))
end)

it("round-trips decoded 64-bit integer cdata through encode", function()
local doc = qjson.parse('{"i":9007199254740993,"u":18446744073709551615}')

assert.are.equal('{"i":9007199254740993}', qjson.encode({ i = doc:get_i64("i") }))
assert.are.equal('{"u":18446744073709551615}', qjson.encode({ u = doc:get_u64("u") }))
end)

it("intentionally differs from lua-cjson by accepting int64 and uint64 cdata", function()
local cjson = require("cjson")

assert.has_error(function()
cjson.encode(9007199254740993LL)
end)
assert.has_error(function()
cjson.encode(18446744073709551615ULL)
end)
assert.are.equal("9007199254740993", qjson.encode(9007199254740993LL))
assert.are.equal("18446744073709551615", qjson.encode(18446744073709551615ULL))
end)

it("rejects non-string object keys", function()
assert_encode_error({name = "value", [2] = "two"}, "qjson.encode: object key must be a string, got number")
assert_encode_error({[true] = 1}, "qjson.encode: object key must be a string, got boolean")
Expand Down
Loading