All pastes #250686 Raw Edit

Daurnimator

public text v1 · immutable
#250686 ·published 2006-11-17 05:40 UTC
rendered paste body
-- Thanks to prec in #lua for the majority of this.

-- Reference:
-- http://wiki.theory.org/BitTorrentSpecification#bencoding
 
local type_decoder
 
local function decode(s, pos)
	pos = pos or 1
	local dd = type_decoder[s:sub(pos,pos)]
	if not dd then
		error(string.format("encoding error at position %d: >>%s[...]<<",
			pos, s:sub(pos, pos + 10)))
	end
	return dd(s, pos)
end
 
local function decode_integer(s, pos)
	local _, pos, n = assert(s:find("^i(-?%d+)e", pos))
	return tonumber(n), pos+1 --rest
end
 
local function decode_string(s, pos)
	local _, pos, len = assert(s:find("^(%d+):", pos))
	return s:sub(pos + 1, pos + len), pos + len + 1
end
 
local function decode_list(s, pos)
	local l = {}
	--local _, pos = assert(s:find("^l.", pos))
	pos = pos+1
	l["__begpos"] = pos-1	
	while not s:match("^e", pos) do
		l[#l + 1], pos = decode(s, pos)
	end
	_, pos = assert(s:find("^e", pos))
		l["__endpos"] = pos
	return l, pos
end
 
local function decode_dict(s, pos)
	local d = {}
	local _, pos = assert(s:find("^d.", pos))
	d["__begpos"] = pos-1	

	while not s:match("^e", pos) do
		local k
		k, pos = decode(s, pos)
		assert(type(k) == "string")
		d[k], pos = decode(s, pos)
	end
	_, pos = assert(s:find("^e", pos))
	d["__endpos"] = pos
	return d, pos
end

local function encode_dict(data)
	local dict = "d"	
	for k,v in pairs(data) do
		v = tonumber(v) or v -- is this required; can a string be a number?
		if(type(v) == "number") then
			dict = dict..#k..':'..k..'i'..v..'e'
		elseif(type(v) == "string") then
			dict = dict..#k..':'..k..#v..':'..v
		end
	end
	dict = dict .. 'e'
	return dict
end

type_decoder = {
	i = decode_integer, l = decode_list, d = decode_dict,
	["0"] = decode_string, ["1"] = decode_string,
	["2"] = decode_string, ["3"] = decode_string,
	["4"] = decode_string, ["5"] = decode_string,
	["6"] = decode_string, ["7"] = decode_string,
	["8"] = decode_string, ["9"] = decode_string,
}

debencode = decode