Created
March 6, 2020 02:03
-
-
Save WhiteHusky/c012984d1719b18240968f83362f61c3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[[ | |
| Code by Carlen White | |
| ]]-- | |
| --[[ | |
| Given a table and a stream to write to, a table is converted to binary | |
| data that can be reversed to recreate the table. | |
| Use case is where the goal is to transmit a table but low memory | |
| systems make it impossible to seralize the response through typical | |
| libaries. Or limits of the means to transmit cannot allow transmission of | |
| a serialized table as a whole. | |
| x0000000 = end table | |
| x0000001 = boolean | |
| x0000010 = number | |
| x0000011 = string | |
| x0000100 = table | |
| booleans use the 8th bit to determine if it is true or false. | |
| numbers are followed by a eight bytes containing the number in binary lua | |
| number format | |
| strings are followed by a four byte unsigned integer describing the length | |
| of the string followed by those characters | |
| tables simply starts the same function on the nested table. | |
| ]]-- | |
| local allowedTableKeys = { | |
| boolean=true, | |
| number=true, | |
| string=true | |
| } | |
| local allowedTableValues = { | |
| boolean=true, | |
| number=true, | |
| string=true, | |
| table=true | |
| } | |
| local streamingSerialization = {} | |
| local function thingToBinary(strm, thing) | |
| local thingType = type(thing) | |
| if thingType == "boolean" then | |
| local d = 1 | |
| if thing then | |
| d = 128 | d | |
| end | |
| strm:write(string.pack(">B", d)) | |
| elseif thingType == "number" then | |
| strm:write(string.pack(">B", 2)) | |
| strm:write(string.pack(">n", thing)) | |
| elseif thingType == "string" then | |
| strm:write(string.pack(">B", 3)) | |
| strm:write(string.pack(">I4", thing:len())) | |
| strm:write(thing) | |
| end | |
| end | |
| function streamingSerialization.pack(strm, t) | |
| for key, value in pairs(t) do | |
| local keyType = type(key) | |
| local valueType = type(value) | |
| if allowedTableKeys[keyType] and allowedTableValues[valueType] then | |
| thingToBinary(strm, key) | |
| if valueType == "table" then | |
| strm:write(string.pack(">B", 4)) | |
| streamingSerialization.pack(strm, value) | |
| else | |
| thingToBinary(strm, value) | |
| end | |
| end | |
| end | |
| strm:write(string.pack(">B",0)) | |
| end | |
| local function binaryToThing(strm) | |
| local raw = string.unpack(">B", strm:read(1)) | |
| local rawType = raw & 7 | |
| local thing = nil | |
| if rawType == 1 then -- boolean | |
| thing = false | |
| if (raw & 128) == 128 then | |
| thing = true | |
| end | |
| elseif rawType == 2 then -- number | |
| thing = string.unpack(">n", strm:read(8)) | |
| elseif rawType == 3 then -- string | |
| local length = string.unpack(">I4", strm:read(4)) | |
| thing = strm:read(length) | |
| elseif rawType == 4 then -- table | |
| thing = streamingSerialization.unpack(strm) | |
| end | |
| return thing | |
| end | |
| function streamingSerialization.unpack(strm) | |
| local t = {} | |
| local key = binaryToThing(strm) | |
| while key do | |
| t[key] = binaryToThing(strm) | |
| key = binaryToThing(strm) | |
| end | |
| return t | |
| end | |
| return streamingSerialization |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment