local extract = bit32.extract
local replace = bit32.replace
local gmatch = string.gmatch
local char = string.char
local pck = string.pack
local unpck = string.unpack
local lshift = bit32.lshift
local rshift = bit32.rshift
local format = string.format
local byte = string.byte
local tostring = tostring
local tonumber = tonumber
local gsub = string.gsub
local rep = string.rep
local sub = string.sub
local r = 33

@native
local function encode(num)
	local str = pck("d",num)
	local f = unpck("I",str:sub(1,4))
	local s = unpck("I",str:sub(5,8))
	return format("%s%s%s%s%s%s%s%s%s%s%s",
		char(extract(f,0,6)+r),
		char(extract(f,6,6)+r),
		char(extract(f,12,6)+r),
		char(extract(f,18,6)+r),
		char(extract(f,24,6)+r),	
		char(extract(s,0,6)+r),
		char(extract(s,6,6)+r),
		char(extract(s,12,6)+r),
		char(extract(s,18,6)+r),
		char(extract(s,24,6)+r),
		char(replace(extract(f,30,2),extract(s,30,2),2,2)+r)
	)
end
@native
local function decode(str)
	local a,b,c,d,e,f,g,h,i,j,k = byte(str,1,11)
	k = k - r
	local s = replace(replace(replace(replace(replace(f-r,g-r,6,6),h-r,12,6),i-r,18,6),j-r,24,6),extract(k,2,2),30,2)
	local f = replace(replace(replace(replace(replace(a-r,b-r,6,6),c-r,12,6),d-r,18,6),e-r,24,6),extract(k,0,2),30,2)
	local a = unpck("d",pck("I",f)..pck("I",s))
	return a
end
@native
local function rle_encode(str)
	--print("nuttin",str)
	str = gsub(str,"%$","$$")
	--print("dollars sanitised",str)
	str = gsub(str,"(!!!!?!?!?!?!?!?)",function(rep)
		return format("$%i",#rep)
	end)
	--print("repeats replaced",str)
	return str
end
@native
local function rle_decode(str)
	str = gsub(str,"(%$+)(%d)",function(first,num)
		if (#first % 2 == 0) then return first..num end 
		return rep("$",#first-1)..rep("!",tonumber(num))
	end)
	--print("repeats removed",str)
	str = gsub(str,"%$%$","$")
	--print("dollars desanities",str)
	return str
end

return {decode = decode, encode = encode, rle_encode = rle_encode, rle_decode = rle_decode}
