initial commit
This commit is contained in:
21
External/EmbeddedLibs/LibSerialize/LICENSE
vendored
Normal file
21
External/EmbeddedLibs/LibSerialize/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Ross Nichols
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1304
External/EmbeddedLibs/LibSerialize/LibSerialize.lua
vendored
Normal file
1304
External/EmbeddedLibs/LibSerialize/LibSerialize.lua
vendored
Normal file
File diff suppressed because it is too large
Load Diff
272
External/EmbeddedLibs/LibSerialize/README.md
vendored
Normal file
272
External/EmbeddedLibs/LibSerialize/README.md
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
# LibSerialize
|
||||
|
||||
LibSerialize is a Lua library for efficiently serializing/deserializing arbitrary values.
|
||||
It supports serializing nils, numbers, booleans, strings, and tables containing these types.
|
||||
|
||||
It is best paired with [LibDeflate](https://github.com/safeteeWow/LibDeflate), to compress
|
||||
the serialized output and optionally encode it for World of Warcraft addon or chat channels.
|
||||
IMPORTANT: if you decide not to compress the output and plan on transmitting over an addon
|
||||
channel, it still needs to be encoded, but encoding via `LibDeflate:EncodeForWoWAddonChannel()`
|
||||
or `LibCompress:GetAddonEncodeTable()` will likely inflate the size of the serialization
|
||||
by a considerable amount. See the usage below for an alternative.
|
||||
|
||||
Note that serialization and compression are sensitive to the specifics of your data set.
|
||||
You should experiment with the available libraries (LibSerialize, AceSerializer, LibDeflate,
|
||||
LibCompress, etc.) to determine which combination works best for you.
|
||||
|
||||
|
||||
## Usage:
|
||||
|
||||
```lua
|
||||
-- Dependencies: AceAddon-3.0, AceComm-3.0, LibSerialize, LibDeflate
|
||||
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceComm-3.0")
|
||||
local LibSerialize = LibStub("LibSerialize")
|
||||
local LibDeflate = LibStub("LibDeflate")
|
||||
|
||||
function MyAddon:OnEnable()
|
||||
self:RegisterComm("MyPrefix")
|
||||
end
|
||||
|
||||
-- With compression (recommended):
|
||||
function MyAddon:Transmit(data)
|
||||
local serialized = LibSerialize:Serialize(data)
|
||||
local compressed = LibDeflate:CompressDeflate(serialized)
|
||||
local encoded = LibDeflate:EncodeForWoWAddonChannel(compressed)
|
||||
self:SendCommMessage("MyPrefix", encoded, "WHISPER", UnitName("player"))
|
||||
end
|
||||
|
||||
function MyAddon:OnCommReceived(prefix, payload, distribution, sender)
|
||||
local decoded = LibDeflate:DecodeForWoWAddonChannel(payload)
|
||||
if not decoded then return end
|
||||
local decompressed = LibDeflate:DecompressDeflate(decoded)
|
||||
if not decompressed then return end
|
||||
local success, data = LibSerialize:Deserialize(decompressed)
|
||||
if not success then return end
|
||||
|
||||
-- Handle `data`
|
||||
end
|
||||
|
||||
-- Without compression (custom codec):
|
||||
MyAddon._codec = LibDeflate:CreateCodec("\000", "\255", "")
|
||||
function MyAddon:Transmit(data)
|
||||
local serialized = LibSerialize:Serialize(data)
|
||||
local encoded = self._codec:Encode(serialized)
|
||||
self:SendCommMessage("MyPrefix", encoded, "WHISPER", UnitName("player"))
|
||||
end
|
||||
function MyAddon:OnCommReceived(prefix, payload, distribution, sender)
|
||||
local decoded = self._codec:Decode(payload)
|
||||
if not decoded then return end
|
||||
local success, data = LibSerialize:Deserialize(decoded)
|
||||
if not success then return end
|
||||
|
||||
-- Handle `data`
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
## API:
|
||||
* **`LibSerialize:SerializeEx(opts, ...)`**
|
||||
|
||||
Arguments:
|
||||
* `opts`: options (see below)
|
||||
* `...`: a variable number of serializable values
|
||||
|
||||
Returns:
|
||||
* result: `...` serialized as a string
|
||||
|
||||
* **`LibSerialize:Serialize(...)`**
|
||||
|
||||
Arguments:
|
||||
* `...`: a variable number of serializable values
|
||||
|
||||
Returns:
|
||||
* `result`: `...` serialized as a string
|
||||
|
||||
Calls `SerializeEx(opts, ...)` with the default options (see below)
|
||||
|
||||
* **`LibSerialize:Deserialize(input)`**
|
||||
|
||||
Arguments:
|
||||
* `input`: a string previously returned from `LibSerialize:Serialize()`
|
||||
|
||||
Returns:
|
||||
* `success`: a boolean indicating if deserialization was successful
|
||||
* `...`: the deserialized value(s), or a string containing the encountered Lua error
|
||||
|
||||
* **`LibSerialize:DeserializeValue(input)`**
|
||||
|
||||
Arguments:
|
||||
* `input`: a string previously returned from `LibSerialize:Serialize()`
|
||||
|
||||
Returns:
|
||||
* `...`: the deserialized value(s)
|
||||
|
||||
* **`LibSerialize:IsSerializableType(...)`**
|
||||
|
||||
Arguments:
|
||||
* `...`: a variable number of values
|
||||
|
||||
Returns:
|
||||
* `result`: true if all of the values' types are serializable.
|
||||
|
||||
Note that if you pass a table, it will be considered serializable
|
||||
even if it contains unserializable keys or values. Only the types
|
||||
of the arguments are checked.
|
||||
|
||||
`Serialize()` will raise a Lua error if the input cannot be serialized.
|
||||
This will occur if any of the following exceed 16777215: any string length,
|
||||
any table key count, number of unique strings, number of unique tables.
|
||||
It will also occur by default if any unserializable types are encountered,
|
||||
though that behavior may be disabled (see options).
|
||||
|
||||
`Deserialize()` and `DeserializeValue()` are equivalent, except the latter
|
||||
returns the deserialization result directly and will not catch any Lua
|
||||
errors that may occur when deserializing invalid input.
|
||||
|
||||
Note that none of the serialization/deseriazation methods support reentrancy,
|
||||
and modifying tables during the serialization process is unspecified and
|
||||
should be avoided. Table serialization is multi-phased and assumes a consistent
|
||||
state for the key/value pairs across the phases.
|
||||
|
||||
|
||||
## Options:
|
||||
The following serialization options are supported:
|
||||
* `errorOnUnserializableType`: `boolean` (default true)
|
||||
* `true`: unserializable types will raise a Lua error
|
||||
* `false`: unserializable types will be ignored. If it's a table key or value,
|
||||
the key/value pair will be skipped. If it's one of the arguments to the
|
||||
call to SerializeEx(), it will be replaced with `nil`.
|
||||
* `stable`: `boolean` (default false)
|
||||
* `true`: the resulting string will be stable, even if the input includes
|
||||
maps. This option comes with an extra memory usage and CPU time cost.
|
||||
* `false`: the resulting string will be unstable and will potentially differ
|
||||
between invocations if the input includes maps
|
||||
* `filter`: `function(t, k, v) => boolean` (default nil)
|
||||
* If specified, the function will be called on every key/value pair in every
|
||||
table encountered during serialization. The function must return true for
|
||||
the pair to be serialized. It may be called multiple times on a table for
|
||||
the same key/value pair. See notes on reeentrancy and table modification.
|
||||
|
||||
If an option is unspecified in the table, then its default will be used.
|
||||
This means that if an option `foo` defaults to true, then:
|
||||
* `myOpts.foo = false`: option `foo` is false
|
||||
* `myOpts.foo = nil`: option `foo` is true
|
||||
|
||||
|
||||
## Customizing table serialization:
|
||||
For any serialized table, LibSerialize will check for the presence of a
|
||||
metatable key `__LibSerialize`. It will be interpreted as a table with
|
||||
the following possible keys:
|
||||
* `filter`: `function(t, k, v) => boolean`
|
||||
* If specified, the function will be called on every key/value pair in that
|
||||
table. The function must return true for the pair to be serialized. It may
|
||||
be called multiple times on a table for the same key/value pair. See notes
|
||||
on reeentrancy and table modification. If combined with the `filter` option,
|
||||
both functions must return true.
|
||||
|
||||
|
||||
## Examples:
|
||||
1. `LibSerialize:Serialize()` supports variadic arguments and arbitrary key types,
|
||||
maintaining a consistent internal table identity.
|
||||
```lua
|
||||
local t = { "test", [false] = {} }
|
||||
t[ t[false] ] = "hello"
|
||||
local serialized = LibSerialize:Serialize(t, "extra")
|
||||
local success, tab, str = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab[1] == "test")
|
||||
assert(tab[ tab[false] ] == "hello")
|
||||
assert(str == "extra")
|
||||
```
|
||||
|
||||
2. Normally, unserializable types raise an error when encountered during serialization,
|
||||
but that behavior can be disabled in order to silently ignore them instead.
|
||||
```lua
|
||||
local serialized = LibSerialize:SerializeEx(
|
||||
{ errorOnUnserializableType = false },
|
||||
print, { a = 1, b = print })
|
||||
local success, fn, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(fn == nil)
|
||||
assert(tab.a == 1)
|
||||
assert(tab.b == nil)
|
||||
```
|
||||
|
||||
3. Tables may reference themselves recursively and will still be serialized properly.
|
||||
```lua
|
||||
local t = { a = 1 }
|
||||
t.t = t
|
||||
t[t] = "test"
|
||||
local serialized = LibSerialize:Serialize(t)
|
||||
local success, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab.t.t.t.t.t.t.a == 1)
|
||||
assert(tab[tab.t] == "test")
|
||||
```
|
||||
|
||||
4. You may specify a global filter that applies to all tables encountered during
|
||||
serialization, and to individual tables via their metatable.
|
||||
```lua
|
||||
local t = { a = 1, b = print, c = 3 }
|
||||
local nested = { a = 1, b = print, c = 3 }
|
||||
t.nested = nested
|
||||
setmetatable(nested, { __LibSerialize = {
|
||||
filter = function(t, k, v) return k ~= "c" end
|
||||
}})
|
||||
local opts = {
|
||||
filter = function(t, k, v) return LibSerialize:IsSerializableType(k, v) end
|
||||
}
|
||||
local serialized = LibSerialize:SerializeEx(opts, t)
|
||||
local success, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab.a == 1)
|
||||
assert(tab.b == nil)
|
||||
assert(tab.c == 3)
|
||||
assert(tab.nested.a == 1)
|
||||
assert(tab.nested.b == nil)
|
||||
assert(tab.nested.c == nil)
|
||||
```
|
||||
|
||||
|
||||
## Encoding format:
|
||||
Every object is encoded as a type byte followed by type-dependent payload.
|
||||
|
||||
For numbers, the payload is the number itself, using a number of bytes
|
||||
appropriate for the number. Small numbers can be embedded directly into
|
||||
the type byte, optionally with an additional byte following for more
|
||||
possible values. Negative numbers are encoded as their absolute value,
|
||||
with the type byte indicating that it is negative. Floats are decomposed
|
||||
into their eight bytes, unless serializing as a string is shorter.
|
||||
|
||||
For strings and tables, the length/count is also encoded so that the
|
||||
payload doesn't need a special terminator. Small counts can be embedded
|
||||
directly into the type byte, whereas larger counts are encoded directly
|
||||
following the type byte, before the payload.
|
||||
|
||||
Strings are stored directly, with no transformations. Tables are stored
|
||||
in one of three ways, depending on their layout:
|
||||
* Array-like: all keys are numbers starting from 1 and increasing by 1.
|
||||
Only the table's values are encoded.
|
||||
* Map-like: the table has no array-like keys.
|
||||
The table is encoded as key-value pairs.
|
||||
* Mixed: the table has both map-like and array-like keys.
|
||||
The table is encoded first with the values of the array-like keys,
|
||||
followed by key-value pairs for the map-like keys. For this version,
|
||||
two counts are encoded, one each for the two different portions.
|
||||
|
||||
Strings and tables are also tracked as they are encountered, to detect reuse.
|
||||
If a string or table is reused, it is encoded instead as an index into the
|
||||
tracking table for that type. Strings must be >2 bytes in length to be tracked.
|
||||
Tables may reference themselves recursively.
|
||||
|
||||
|
||||
#### Type byte:
|
||||
The type byte uses the following formats to implement the above:
|
||||
|
||||
* `NNNN NNN1`: a 7 bit non-negative int
|
||||
* `CCCC TT10`: a 2 bit type index and 4 bit count (strlen, #tab, etc.)
|
||||
* Followed by the type-dependent payload
|
||||
* `NNNN S100`: the lower four bits of a 12 bit int and 1 bit for its sign
|
||||
* Followed by a byte for the upper bits
|
||||
* `TTTT T000`: a 5 bit type index
|
||||
* Followed by the type-dependent payload, including count(s) if needed
|
||||
4
External/EmbeddedLibs/LibSerialize/lib.xml
vendored
Normal file
4
External/EmbeddedLibs/LibSerialize/lib.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="LibSerialize.lua" />
|
||||
</Ui>
|
||||
301
External/EmbeddedLibs/LibSerialize/tests.lua
vendored
Normal file
301
External/EmbeddedLibs/LibSerialize/tests.lua
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
local LibSerialize = require("LibSerialize")
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local tostring = tostring
|
||||
local assert = assert
|
||||
local unpack = unpack
|
||||
local pcall = pcall
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Examples from the top of LibSerialize.lua
|
||||
--]]---------------------------------------------------------------------------
|
||||
|
||||
do
|
||||
local t = { "test", [false] = {} }
|
||||
t[ t[false] ] = "hello"
|
||||
local serialized = LibSerialize:Serialize(t, "extra")
|
||||
local success, tab, str = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab[1] == "test")
|
||||
assert(tab[ tab[false] ] == "hello")
|
||||
assert(str == "extra")
|
||||
end
|
||||
|
||||
do
|
||||
local serialized = LibSerialize:SerializeEx(
|
||||
{ errorOnUnserializableType = false },
|
||||
print, { a = 1, b = print })
|
||||
local success, fn, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(fn == nil)
|
||||
assert(tab.a == 1)
|
||||
assert(tab.b == nil)
|
||||
end
|
||||
|
||||
do
|
||||
local t = { a = 1 }
|
||||
t.t = t
|
||||
t[t] = "test"
|
||||
local serialized = LibSerialize:Serialize(t)
|
||||
local success, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab.t.t.t.t.t.t.a == 1)
|
||||
assert(tab[tab.t] == "test")
|
||||
end
|
||||
|
||||
do
|
||||
local t = { a = 1, b = print, c = 3 }
|
||||
local nested = { a = 1, b = print, c = 3 }
|
||||
t.nested = nested
|
||||
setmetatable(nested, { __LibSerialize = {
|
||||
filter = function(t, k, v) return k ~= "c" end
|
||||
}})
|
||||
local opts = {
|
||||
filter = function(t, k, v) return LibSerialize:IsSerializableType(k, v) end
|
||||
}
|
||||
local serialized = LibSerialize:SerializeEx(opts, t)
|
||||
local success, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab.a == 1)
|
||||
assert(tab.b == nil)
|
||||
assert(tab.c == 3)
|
||||
assert(tab.nested.a == 1)
|
||||
assert(tab.nested.b == nil)
|
||||
assert(tab.nested.c == nil)
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Test of stable serialization
|
||||
--]]---------------------------------------------------------------------------
|
||||
|
||||
do
|
||||
local t = { a = 1, b = print, c = 3 }
|
||||
local nested = { a = 1, b = print, c = 3 }
|
||||
t.nested = nested
|
||||
setmetatable(nested, { __LibSerialize = {
|
||||
filter = function(t, k, v) return k ~= "c" end
|
||||
}})
|
||||
local opts = {
|
||||
filter = function(t, k, v) return LibSerialize:IsSerializableType(k, v) end,
|
||||
stable = true
|
||||
}
|
||||
local serialized = LibSerialize:SerializeEx(opts, t)
|
||||
local success, tab = LibSerialize:Deserialize(serialized)
|
||||
assert(success)
|
||||
assert(tab.a == 1)
|
||||
assert(tab.b == nil)
|
||||
assert(tab.c == 3)
|
||||
assert(tab.nested.a == 1)
|
||||
assert(tab.nested.b == nil)
|
||||
assert(tab.nested.c == nil)
|
||||
end
|
||||
|
||||
do
|
||||
local t1 = { x = "y", "test", [false] = { 1, 2, 3, a = "b" } }
|
||||
local opts = {
|
||||
stable = true,
|
||||
filter = function(t, k, v) return not tonumber(k) or tonumber(k) < 100 end
|
||||
}
|
||||
local serialized1 = LibSerialize:SerializeEx(opts, t1)
|
||||
local success1, tab1 = LibSerialize:Deserialize(serialized1)
|
||||
assert(success1)
|
||||
assert(tab1[1] == "test")
|
||||
assert(tab1.x == "y")
|
||||
assert(tab1[false][1] == 1)
|
||||
assert(tab1[false][2] == 2)
|
||||
assert(tab1[false][3] == 3)
|
||||
assert(tab1[false].a == "b")
|
||||
|
||||
-- make a copy of the original table, but first insert a bunch of extra keys (which we'll
|
||||
-- filter out) to force the order of the hashes to be different (tested with lua 5.1 and 5.2)
|
||||
local t2 = {}
|
||||
for i = 100, 10000 do
|
||||
t2[tostring(i)] = i
|
||||
end
|
||||
t2.x = "y"
|
||||
t2[1] = "test"
|
||||
t2[false] = { 1, 2, 3, a = "b" }
|
||||
|
||||
-- ensure the iteration order is different
|
||||
local isDifferent = false
|
||||
local k1, k2 = nil, nil
|
||||
while true do
|
||||
k1 = next(t1, k1)
|
||||
-- get the next key from t2 that's not going to be filtered
|
||||
while true do
|
||||
k2 = next(t2, k2)
|
||||
if k2 == nil or not tonumber(k2) or tonumber(k2) < 100 then
|
||||
break
|
||||
end
|
||||
end
|
||||
if k1 == nil and k2 == nil then
|
||||
break
|
||||
end
|
||||
assert(k1 ~= nil and k2 ~= nil)
|
||||
isDifferent = isDifferent or k1 ~= k2
|
||||
end
|
||||
assert(isDifferent)
|
||||
|
||||
-- serialize the copy and ensure the result is the same
|
||||
local serialized2 = LibSerialize:SerializeEx(opts, t2)
|
||||
assert(serialized2 == serialized1)
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Utilities
|
||||
--]]---------------------------------------------------------------------------
|
||||
|
||||
local function tCompare(lhsTable, rhsTable, depth)
|
||||
depth = depth or 1
|
||||
for key, value in pairs(lhsTable) do
|
||||
if type(value) == "table" then
|
||||
local rhsValue = rhsTable[key]
|
||||
if type(rhsValue) ~= "table" then
|
||||
return false
|
||||
end
|
||||
if depth > 1 then
|
||||
if not tCompare(value, rhsValue, depth - 1) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
elseif value ~= rhsTable[key] then
|
||||
-- print("mismatched value: " .. key .. ": " .. tostring(value) .. ", " .. tostring(rhsTable[key]))
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- Check for any keys that are in rhsTable and not lhsTable.
|
||||
for key, value in pairs(rhsTable) do
|
||||
if lhsTable[key] == nil then
|
||||
-- print("mismatched key: " .. key)
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Test cases for serialization
|
||||
--]]---------------------------------------------------------------------------
|
||||
|
||||
local function fail(value, desc)
|
||||
assert(false, ("Test failed (%s): %s"):format(tostring(value), desc))
|
||||
end
|
||||
|
||||
local function testfilter(t, k, v)
|
||||
return k ~= "banned" and v ~= "banned"
|
||||
end
|
||||
|
||||
local function check(value, bytelen, cmp)
|
||||
local serialized = LibSerialize:SerializeEx({ errorOnUnserializableType = false, filter = testfilter }, value)
|
||||
if #serialized ~= bytelen then
|
||||
fail(value, ("Unexpected serialized length (%d, expected %d)"):format(#serialized, bytelen))
|
||||
end
|
||||
|
||||
local success, deserialized = LibSerialize:Deserialize(serialized)
|
||||
if not success then
|
||||
fail(value, ("Deserialization failed: %s"):format(deserialized))
|
||||
end
|
||||
|
||||
local typ = type(value)
|
||||
if typ == "table" and not tCompare(cmp or value, deserialized) then
|
||||
fail(value, "Non-matching deserialization result")
|
||||
elseif typ ~= "table" and value ~= deserialized then
|
||||
fail(value, ("Non-matching deserialization result: %s"):format(tostring(deserialized)))
|
||||
end
|
||||
end
|
||||
|
||||
-- Format: each test case is { value, bytelen, cmp }. The value will be serialized
|
||||
-- and then deserialized, checking for success and equality, and the length of
|
||||
-- the serialized string will be compared against bytelen. If `cmp` is provided,
|
||||
-- it will be used for comparison against the deserialized result instead of `value`.
|
||||
-- Note that the length always contains one extra byte for the version number.
|
||||
local testCases = {
|
||||
{ nil, 2 },
|
||||
{ true, 2 },
|
||||
{ false, 2 },
|
||||
{ 0, 2 },
|
||||
{ 1, 2 },
|
||||
{ 127, 2 },
|
||||
{ 128, 3 },
|
||||
{ 4095, 3 },
|
||||
{ 4096, 4 },
|
||||
{ 65535, 4 },
|
||||
{ 65536, 5 },
|
||||
{ 16777215, 5 },
|
||||
{ 16777216, 6 },
|
||||
{ 4294967295, 6 },
|
||||
{ 4294967296, 9 },
|
||||
{ 9007199254740992, 9 },
|
||||
{ 1.5, 6 },
|
||||
{ 27.32, 8 },
|
||||
{ 123.45678901235, 10 },
|
||||
{ 148921291233.23, 10 },
|
||||
{ -1, 3 },
|
||||
{ -4095, 3 },
|
||||
{ -4096, 4 },
|
||||
{ -65535, 4 },
|
||||
{ -65536, 5 },
|
||||
{ -16777215, 5 },
|
||||
{ -16777216, 6 },
|
||||
{ -4294967295, 6 },
|
||||
{ -4294967296, 9 },
|
||||
{ -9007199254740992, 9 },
|
||||
{ -1.5, 6 },
|
||||
{ -123.45678901235, 10 },
|
||||
{ -148921291233.23, 10 },
|
||||
{ "", 2 },
|
||||
{ "a", 3 },
|
||||
{ "abcdefghijklmno", 17 },
|
||||
{ "abcdefghijklmnop", 19 },
|
||||
{ ("1234567890"):rep(30), 304 },
|
||||
{ {}, 2 },
|
||||
{ { 1 }, 3 },
|
||||
{ { 1, 2, 3, 4, 5 }, 7 },
|
||||
{ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 17 },
|
||||
{ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, 19 },
|
||||
{ { 1, 2, 3, 4, a = 1, b = 2, [true] = 3, d = 4 }, 17 },
|
||||
{ { 1, 2, 3, 4, 5, a = 1, b = 2, c = true, d = 4 }, 21 },
|
||||
{ { 1, 2, 3, 4, 5, a = 1, b = 2, c = 3, d = 4, e = false }, 24 },
|
||||
{ { a = 1, b = 2, c = 3 }, 11 },
|
||||
{ { "aa", "bb", "aa", "bb" }, 14 },
|
||||
{ { "aa1", "bb2", "aa3", "bb4" }, 18 },
|
||||
{ { "aa1", "bb2", "aa1", "bb2" }, 14 },
|
||||
{ { "aa1", "bb2", "bb2", "aa1" }, 14 },
|
||||
{ { "abcdefghijklmno", "abcdefghijklmno", "abcdefghijklmno", "abcdefghijklmno" }, 24 },
|
||||
{ { "abcdefghijklmno", "abcdefghijklmno", "abcdefghijklmno", "abcdefghijklmnop" }, 40 },
|
||||
{ { 1, 2, 3, print, print, 6 }, 7, { 1, 2, 3, nil, nil, 6 } },
|
||||
{ { 1, 2, 3, print, 5, 6 }, 8, { 1, 2, 3, nil, 5, 6 } },
|
||||
{ { a = print, b = 1, c = print }, 5, { b = 1 } },
|
||||
{ { a = print, [print] = "a" }, 2, {} },
|
||||
{ { "banned", 1, 2, 3, banned = 4, test = "banned", a = 1 }, 9, { nil, 1, 2, 3, a = 1 } },
|
||||
}
|
||||
|
||||
do
|
||||
local t = { a = 1, b = 2 }
|
||||
table.insert(testCases, { { t, t, t }, 13 })
|
||||
table.insert(testCases, { { { a = 1, b = 2 }, { a = 1, b = 2 }, { a = 1, b = 2 } }, 23 })
|
||||
end
|
||||
|
||||
for _, testCase in ipairs(testCases) do
|
||||
check(unpack(testCase))
|
||||
end
|
||||
|
||||
-- Since all the above tests assume serialization success, try some failures now.
|
||||
local failCases = {
|
||||
{ print },
|
||||
{ [print] = true },
|
||||
{ [true] = print },
|
||||
print,
|
||||
}
|
||||
|
||||
for _, testCase in ipairs(failCases) do
|
||||
local success = pcall(LibSerialize.Serialize, LibSerialize, testCase)
|
||||
assert(success == false)
|
||||
end
|
||||
|
||||
print("All tests passed!")
|
||||
Reference in New Issue
Block a user