Last active
December 3, 2022 22:16
-
-
Save mieszko4/01bab59fdeba6bd09bf475dda5968808 to your computer and use it in GitHub Desktop.
Revisions
-
mieszko4 revised this gist
Dec 3, 2022 . No changes.There are no files selected for viewing
-
mieszko4 revised this gist
Dec 3, 2022 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -6,9 +6,9 @@ local function extractChar(unit, idx) -- Skip mask for first ASCII char since shifting will destroy other two parts if idx == 2 then local charCode = (unit) >> (8 * idx) return string.char(charCode) end -- Extract specific 8-bit -
mieszko4 revised this gist
Dec 3, 2022 . 1 changed file with 7 additions and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,13 @@ -- Define function to extract 8-bit ASCII char from 24-bit base64 unit local function extractChar(unit, idx) -- Skip mask for first ASCII char since shifting will destroy other two parts if idx == 2 then local charCode = (unit) >> (8 * idx) return string.char(charCode) end -- Extract specific 8-bit local mask = (2^8 - 1) << (8 * idx) -
mieszko4 revised this gist
Dec 2, 2022 . 1 changed file with 16 additions and 13 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -6,19 +6,14 @@ local function extractChar(unit, idx) -- Extract specific 8-bit local mask = (2^8 - 1) << (8 * idx) -- Move 8-bit to the beginning so it becomes a char code local charCode = (unit & mask) >> (8 * idx) -- Convert to string return string.char(charCode) end -- Define mapping of base64 character to number local mapping = { A=0, B=1, C=2, D=3, E=4, F=5, G=6, H=7, @@ -30,9 +25,11 @@ local function extractChar(unit, idx) w=48, x=49, y=50, z=51, ["0"]=52, ["1"]=53, ["2"]=54, ["3"]=55, ["4"]=56, ["5"]=57, ["6"]=58, ["7"]=59, ["8"]=60, ["9"]=61, ["+"]=62, ["/"]=63 } local padding = "=" local missing = "" local function atob(encodedString) -- Get four 6-bit chunks which forms one unit -- There must be at least two 6-bit chunks to cover at least one 8-bit chunk local decodedString = encodedString:gsub("(.)(.)(.?)(.?)", function(c1, c2, c3, c4) -- Convert each 6-bit chunk to number @@ -44,14 +41,18 @@ local function extractChar(unit, idx) -- Set optional chunks to 0 to be able to multiplex if b3 == nil then b3 = 0 end if b4 == nil then b4 = 0 end -- Multiplex onto 24-bit number local muxedUnit = (b1 << (6 * 3)) + (b2 << (6 * 2)) + (b3 << (6 * 1)) + (b4 << (6 * 0)) -- Extract 8-bit chunks -- Use empty string if unit is not full or it is padded -- and handle A base64 characters at the end of encodedString local r1 = extractChar(muxedUnit, 2) -- if c3 is padding or missing then we can skip r2 local r2 = (c3 == padding or c3 == missing) and "" or extractChar(muxedUnit, 1) -- if c4 is padding or missing then we can skip r3 local r3 = (c4 == padding or c4 == missing) and "" or extractChar(muxedUnit, 0) -- Concatanate return r1..r2..r3 @@ -62,7 +63,9 @@ end return atob -- Test plan assert(atob("bGlnaHQgd28=") == "light wo", "full units, single padding") assert(atob("bGlnaHQgd28A") == "light wo\x00", "full units, explicit A") assert(atob("bGlnaHQgd28") == "light wo", "2/3 of unit") assert(atob("bGlnaHQgdw==") == "light w", "full unit, double padding") assert(atob("bGlnaHQgdw") == "light w", "1/3 of unit") -
mieszko4 created this gist
Dec 2, 2022 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,70 @@ -- Lua uses at least 8 bytes to represent a number -- Base64 minimum processable unit is represented by four 6-bit chunks which is 24-bits => 3 bytes -- Hence we can safely use bit operations on number type for multiplexing and extraction -- Define function to extract 8-bit ASCII char from 24-bit base64 unit local function extractChar(unit, idx) -- Extract specific 8-bit local mask = (2^8 - 1) << (8 * idx) -- Move 8-bit to the beginning so it becomes a char code local charCode = (unit & mask) >> (8 * idx) -- Return empty string in case of padding if charCode == 0 then return "" end -- Convert to string return string.char(charCode) end -- Define mapping of base64 character to number local mapping = { A=0, B=1, C=2, D=3, E=4, F=5, G=6, H=7, I=8, J=9, K=10, L=11, M=12, N=13, O=14, P=15, Q=16, R=17, S=18, T=19, U=20, V=21, W=22, X=23, Y=24, Z=25, a=26, b=27, c=28, d=29, e=30, f=31, g=32, h=33, i=34, j=35, k=36, l=37, m=38, n=39, o=40, p=41, q=42, r=43, s=44, t=45, u=46, v=47, w=48, x=49, y=50, z=51, ["0"]=52, ["1"]=53, ["2"]=54, ["3"]=55, ["4"]=56, ["5"]=57, ["6"]=58, ["7"]=59, ["8"]=60, ["9"]=61, ["+"]=62, ["/"]=63 } local function atob(encodedString) -- Get four 6-bit chunks -- There must be at least two 6-bit chunks to cover at least one 8-bit chunk local decodedString = encodedString:gsub("(.)(.)(.?)(.?)", function(c1, c2, c3, c4) -- Convert each 6-bit chunk to number local b1 = mapping[c1] --24,23,22,21,20,19 local b2 = mapping[c2] --18,17,16,15,14,13 local b3 = mapping[c3] --12,11,10,09,08,07 local b4 = mapping[c4] --06,05,04,03,02,01 -- Set optional chunks to 0 to be able to multiplex if b3 == nil then b3 = 0 end if b4 == nil then b4 = 0 end -- Multiplex onto 24-bit number local muxedUnit = (b1 << (6 * 3)) + (b2 << (6 * 2)) + (b3 << (6 * 1)) + (b4 << (6 * 0)) -- Extract 8-bit chunks local r1 = extractChar(muxedUnit, 2) local r2 = extractChar(muxedUnit, 1) local r3 = extractChar(muxedUnit, 0) -- Concatanate return r1..r2..r3 end) return decodedString end return atob assert(atob("bGlnaHQgd28=") == "light wo", "full units, single padding") assert(atob("bGlnaHQgd28") == "light wo", "2/3 of unit") assert(atob("bGlnaHQgdw==") == "light w", "full unit, double padding") assert(atob("bGlnaHQgdw") == "light w", "1/3 of unit") assert(atob("bGlnaHQgd28=") == "light wo", "full units, single padding") assert(atob("bGlnaHQgd29y") == "light wor", "full units, no padding")