local t={}t.__index=t function t.new(n)local a={Position=1;Buffer=n,Length=#n}return setmetatable(a,t)end function t.ReadByte(t)local n=t.Buffer local a=t.Position if a<=t.Length then local E=n:sub(a,a)t.Position=a+1 return E:byte()end end function t.ReadBytes(a,t,n)local E={}for t=1,t,1 do E[t]=a:ReadByte()end if n then return E end return unpack(E)end function t.ReadAllBytes(t)return t:ReadBytes(t.Length,true)end function t.IterateBytes(t)return function()return t:ReadByte()end end function t.TwosComplementOf(a,t,n)if t>=2^(n-1)then t=t-2^n end return t end function t.ReadUInt16(t)local n,a=t:ReadBytes(2)return n*256+a end function t.ReadInt16(t)local n=t:ReadUInt16()return t:TwosComplementOf(n,16)end function t.ReadUInt32(t)local n=t:ReadUInt16()local a=t:ReadUInt16()return n*65536+a end function t.ReadInt32(t)local n=t:ReadUInt32()return t:TwosComplementOf(n,32)end function t.ReadString(n,t)if t==nil then t=n:ReadByte()end local a=n.Position local E=math.min(n.Length,a+t)local I=n.Buffer:sub(a,E-1)n.Position=E return I end function t.ForkReader(a,n)local E=a:ReadString(n)return t.new(E)end return t
local BinaryReader = {}
BinaryReader.__index = BinaryReader

function BinaryReader.new(buffer)
	local reader = 
	{
		Position = 1;
		Buffer = buffer;
		Length = #buffer;
	}
	
	return setmetatable(reader, BinaryReader)
end

function BinaryReader:ReadByte()
	local buffer = self.Buffer
	local pos = self.Position
	
	if pos <= self.Length then
		local result = buffer:sub(pos, pos)
		self.Position = pos + 1
		
		return result:byte()
	end
end

function BinaryReader:ReadBytes(count, asArray)
	local values = {}
	
	for i = 1, count do
		values[i] = self:ReadByte()
	end
	
	if asArray then
		return values
	end
	
	return unpack(values)
end

function BinaryReader:ReadAllBytes()
	return self:ReadBytes(self.Length, true)
end

function BinaryReader:IterateBytes()
	return function ()
		return self:ReadByte()
	end
end

function BinaryReader:TwosComplementOf(value, numBits)
	if value >= (2 ^ (numBits - 1)) then
		value = value - (2 ^ numBits)
	end
	
	return value
end

function BinaryReader:ReadUInt16()
	local upper, lower = self:ReadBytes(2)
	return (upper * 256) + lower
end

function BinaryReader:ReadInt16()
	local unsigned = self:ReadUInt16()
	return self:TwosComplementOf(unsigned, 16)
end

function BinaryReader:ReadUInt32()
	local upper = self:ReadUInt16()
	local lower = self:ReadUInt16()
	
	return (upper * 65536) + lower
end

function BinaryReader:ReadInt32()
	local unsigned = self:ReadUInt32()
	return self:TwosComplementOf(unsigned, 32)
end

function BinaryReader:ReadString(length)
    if length == nil then
        length = self:ReadByte()
    end
    
    local pos = self.Position
    local nextPos = math.min(self.Length, pos + length)
    
    local result = self.Buffer:sub(pos, nextPos - 1)
    self.Position = nextPos
    
    return result
end

function BinaryReader:ForkReader(length)
	local chunk = self:ReadString(length)
	return BinaryReader.new(chunk)
end

return BinaryReader