Module:User:Surjection/packer

local export = {} -- see Module:User:Surjection/unpacker for format

local common_keys = { "from", "remove_diacritics", "type", "ancestors", "wikimedia_codes", "wikipedia_article", "translit", "link_tr", "display_text", "entry_name", "sort_key", "dotted_dotless_i", "standardChars" }

local pack_table = nil

local function trim31(s) local trim = #s while trim > 0 and s:byte(trim) == 31 do trim = trim - 1 end if trim < #s then return s:sub(1, trim) end return s end

local function pack_table_value(v, common_keys, implicit) local t = type(v) if v == nil then return "\016" elseif t == "boolean" then return string.char(17, v and 1 or 0) elseif t == "number" then return "\018" .. tostring(v) .. "\031"	elseif t == "string" then return "\019" .. v .. "\031"	elseif t == "table" then return trim31("\020" .. pack_table(v, common_keys)) .. "\003"	else error("cannot encode '" .. t .. "") end end

pack_table = function (tbl, common_keys) local max_index = 0 local s = "" for index, value in ipairs(tbl) do		s = trim31(s) s = s .. pack_table_value(value, common_keys) max_index = index end for key, value in pairs(tbl) do		if type(key) == "number" then if key <= 0 or key > max_index then s = trim31(s) s = string.char(2) .. tostring(key) .. pack_table_value(value, common_keys) end elseif type(key) == "string" then local compression = common_keys[key] local skey if compression ~= nil and compression <= 255 and #key > 2 then s = trim31(s) key = string.char(5, compression) elseif #key == 0 then s = trim31(s) key = string.char(2) end s = s .. key .. pack_table_value(value, common_keys) end end return s end

function export.pack_rows(list, common_keys) local s = "" local common_key_indexes = {}

for index, key in ipairs(common_keys) do		common_key_indexes[key] = index end

for top_key, top_value in pairs(list) do s = s .. string.char(1) .. top_key .. string.char(4) .. pack_table(top_value, common_key_indexes) local trim = #s while trim > 0 and (s:byte(trim) == 3 or s:byte(trim) == 31) do trim = trim - 1 end if trim < #s then s = s:sub(1, trim) end end

return s .. string.char(1) end

export.common_keys = common_keys return export