From fdbc23fab67129d4764367f5fa4614cc244904b3 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Sat, 27 Oct 2018 12:43:03 +0200
Subject: util.serialization: Add option for allowing multiple references to
 the same table (but not cycles)

---
 spec/util_serialization_spec.lua | 16 +++++++++++++++-
 util/serialization.lua           | 10 ++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/spec/util_serialization_spec.lua b/spec/util_serialization_spec.lua
index e73ca826..2af5d803 100644
--- a/spec/util_serialization_spec.lua
+++ b/spec/util_serialization_spec.lua
@@ -25,13 +25,27 @@ describe("util.serialization", function ()
 				t[t] = { t };
 				serialization.serialize(t)
 			end);
+			-- also with multirefs allowed
+			assert.has_error(function ()
+				local t = {}
+				t[t] = { t };
+				serialization.serialize(t, { multirefs = true })
+			end);
 		end);
 
 		it("rejects multiple references to same table", function ()
 			assert.has_error(function ()
 				local t1 = {};
 				local t2 = { t1, t1 };
-				serialization.serialize(t2);
+				serialization.serialize(t2, { multirefs = false });
+			end);
+		end);
+
+		it("optionally allows multiple references to same table", function ()
+			assert.has_error(function ()
+				local t1 = {};
+				local t2 = { t1, t1 };
+				serialization.serialize(t2, { multirefs = true });
 			end);
 		end);
 
diff --git a/util/serialization.lua b/util/serialization.lua
index 998b16de..a8b64c04 100644
--- a/util/serialization.lua
+++ b/util/serialization.lua
@@ -120,6 +120,7 @@ local function new(opt)
 	local hex = opt.hex;
 	local freeze = opt.freeze;
 	local maxdepth = opt.maxdepth or 127;
+	local multirefs = opt.multiref;
 
 	-- serialize one table, recursively
 	-- t - table being serialized
@@ -136,7 +137,10 @@ local function new(opt)
 			return l;
 		end
 
+		-- Keep track of table loops
+		local ot = t; -- reference pre-freeze
 		o[t] = true;
+		o[ot] = true;
 
 		if freeze == true then
 			-- opportunity to do pre-serialization
@@ -200,6 +204,12 @@ local function new(opt)
 			o[l], l = s_rep(indentwith, d-1), l + 1;
 		end
 		o[l], l = tend, l +1;
+
+		if multirefs then
+			o[t] = nil;
+			o[ot] = nil;
+		end
+
 		return l;
 	end
 
-- 
cgit v1.2.3