class BEncode::Parser

Attributes

stream[R]

Public Class Methods

new(stream) click to toggle source
# File lib/bencode/parser.rb, line 7
def initialize(stream)
  @stream =
    if stream.kind_of?(IO) || stream.kind_of?(StringIO)
      stream
    elsif stream.respond_to? :string
      StringIO.new stream.string
    elsif stream.respond_to? :to_s
      StringIO.new stream.to_s
    end
end

Public Instance Methods

eos?() click to toggle source
# File lib/bencode/parser.rb, line 27
def eos?
  stream.eof?
end
parse!() click to toggle source
# File lib/bencode/parser.rb, line 18
def parse!
  case peek
    when ?i then parse_integer!
    when ?l then parse_list!
    when ?d then parse_dict!
    when ?0 .. ?9 then parse_string!
  end
end

Private Instance Methods

parse_dict!() click to toggle source
# File lib/bencode/parser.rb, line 47
def parse_dict!
  stream.getc
  hsh = {}
  until peek == ?e
    key = parse!

    unless key.is_a? String or key.is_a? Fixnum
      raise BEncode::DecodeError, "key must be a string or number"
    end
      
    val = parse!

    hsh.store(key.to_s, val)
  end
  stream.getc
  hsh
end
parse_integer!() click to toggle source
# File lib/bencode/parser.rb, line 33
def parse_integer!
  stream.getc
  num = stream.gets("e") or raise BEncode::DecodeError
  num.chop.to_i
end
parse_list!() click to toggle source
# File lib/bencode/parser.rb, line 39
def parse_list!
  stream.getc
  ary = []
  ary.push(parse!) until peek == ?e
  stream.getc
  ary
end
parse_string!() click to toggle source
# File lib/bencode/parser.rb, line 65
def parse_string!
  num = stream.gets(":") or
    raise BEncode::DecodeError, "invalid string length (no colon)"

  begin
    length = num.chop.to_i
    return "" if length == 0 # Workaround for Rubinius bug
    str = stream.read(length)
  rescue
    raise BEncode::DecodeError, "invalid string length"
  end

  str
end
peek() click to toggle source
# File lib/bencode/parser.rb, line 80
def peek
  c = stream.getc
  stream.ungetc(c)
  c
end