From 5355cb1d87f60bc5548a8a9311e597b9c6046013 Mon Sep 17 00:00:00 2001 From: HybridDog <3192173+HybridDog@users.noreply.github.com> Date: Wed, 22 Apr 2020 16:43:48 +0200 Subject: [PATCH] minetest.serialize: Reversible number serialization (#9722) * minetest.serialize: Reversible number to string conversion The %a format is not supported in Lua 5.1. This commit also adds two tests for number serialization. --- builtin/common/serialize.lua | 11 ++--------- builtin/common/tests/serialize_spec.lua | 12 ++++++++++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index 163aa67a..300b394c 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -120,15 +120,8 @@ function core.serialize(x) elseif tp == "function" then return string.format("loadstring(%q)", string.dump(x)) elseif tp == "number" then - -- Serialize integers with string.format to prevent - -- scientific notation, which doesn't preserve - -- precision and breaks things like node position - -- hashes. Serialize floats normally. - if math.floor(x) == x then - return string.format("%d", x) - else - return tostring(x) - end + -- Serialize numbers reversibly with string.format + return string.format("%.17g", x) elseif tp == "table" then local vals = {} local idx_dumped = {} diff --git a/builtin/common/tests/serialize_spec.lua b/builtin/common/tests/serialize_spec.lua index c41b0a37..17c6a60f 100644 --- a/builtin/common/tests/serialize_spec.lua +++ b/builtin/common/tests/serialize_spec.lua @@ -18,6 +18,18 @@ describe("serialize", function() assert.same(test_in, test_out) end) + it("handles precise numbers", function() + local test_in = 0.2695949158945771 + local test_out = core.deserialize(core.serialize(test_in)) + assert.same(test_in, test_out) + end) + + it("handles big integers", function() + local test_in = 269594915894577 + local test_out = core.deserialize(core.serialize(test_in)) + assert.same(test_in, test_out) + end) + it("handles recursive structures", function() local test_in = { hello = "world" } test_in.foo = test_in