module Bencoding module Parser DICTIONARY_TOKEN = 100 # d # :nodoc: LIST_TOKEN = 108 # l # :nodoc: INTEGER_TOKEN = 105 # i # :nodoc: TERMINATOR_TOKEN = 101 # e # :nodoc: SEPERATOR_TOKEN = 58 # : # :nodoc: def load(io) parse_anytype(io) end def parse_anytype(io, typechar=nil) # :nodoc: typechar ||= io.getc case typechar when DICTIONARY_TOKEN then parse_dictionary(io) when LIST_TOKEN then parse_list(io) when INTEGER_TOKEN then parse_integer(io) else io.ungetc typechar parse_string(io) end end def parse_dictionary(io) # :nodoc: dictionary = ::Hash.new until (c = io.getc) == TERMINATOR_TOKEN io.ungetc c key = parse_string(io) val = parse_anytype(io) dictionary[key] = val end dictionary end def parse_list(io) # :nodoc: list = ::Array.new until (c = io.getc) == TERMINATOR_TOKEN val = parse_anytype(io, c) list << val end list end def parse_integer(io, terminator=TERMINATOR_TOKEN) # :nodoc: integer_string = "" until (c = io.getc) == terminator integer_string << c.chr end integer_string.to_i end def parse_string(io) # :nodoc: length = parse_integer(io, SEPERATOR_TOKEN) io.read(length) end extend self end end