lib/bencode.rb in bencode-0.1.0 vs lib/bencode.rb in bencode-0.3.0
- old
+ new
@@ -1,17 +1,55 @@
-# Thanks to Daniel Martin and all the other lads at ruby-lang for
-# helping me out.
-
-# bencode is a Ruby implementation of the Bencode data serialization
+# = bencode.rb - Bencode Library
+#
+# Bencode is a Ruby implementation of the Bencode data serialization
# format used in the BitTorrent protocol.
#
# == Synopsis
#
# "foobar".bencode #=> "6:foobar"
# 42.bencode #=> "i42e"
# [1, 2, 3].bencode #=> "li1ei2ei3ee"
#
+# Bencoding (pronounced _bee-encode_) is a simple protocol, consiting of
+# only 4 value types.
+#
+# === Integers ===
+#
+# An integer is encoded an _i_ followed by the numeral itself, followed
+# by an _e_. Leading zeros are not allowed. Negative values are prefixed
+# with a minus sign.
+#
+# 42.bencode #=> "i42e"
+# -2.bencode #=> "i-2e"
+# 0.bencode #=> "i0e"
+#
+# === Strings ===
+#
+# Strings are a sequence of zero or more bytes. It is encoded as
+# _<length>:<contents>_, where _length_ is the lenth of _contents_. _length_
+# must be non-negative.
+#
+# "".bencode #=> "0:"
+# "foo".bencode #=> "3:foo"
+#
+# === Lists ===
+#
+# Lists are encoded as _l_ followed by the elements, followed by _e_.
+# There is no element seperator.
+#
+# [1, 2, 3].bencode #=> "li1ei2ei3ee"
+#
+# === Dictionaries ===
+#
+# Dictionaries are encoded as _d<contents>e_, where _contents_ is a sequence
+# of keys and values. Each value is immediately preceded by a key. Keys must
+# be strings, and will appear in lexicographical order.
+#
+# {"foo" => 3, "bar" => 1, "baz" => 2}.bencode
+# #=> "d3:bari1e3:bazi2e3:fooi3ee"
+#
+#
# == Authors
#
# * Daniel Schierbeck
#
# == Contributors
@@ -27,10 +65,11 @@
# version.
#
# Bencode is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
class Object
# Raises an exception. Subclasses of Object must themselves
# define meaningful #bencode methods.
def bencode
@@ -131,54 +170,41 @@
def to_s # :nodoc:
"could not bencode #{@object_class}"
end
end
-class BdecodeError < StandardError
- attr_reader :pos
+class BdecodeError < StandardError; end
- def initialize(pos = nil) # :nodoc:
- @pos = pos
- end
-
- def to_s # :nodoc:
- if pos.nil?
- "syntax error"
- else
- "syntax error near position #{pos}"
- end
- end
-end
-
module Bencode
class << self
+ # Bencodes +obj+
def dump(obj)
obj.bencode
end
+ # Bdecodes +str+
def load(str)
require 'strscan'
scanner = StringScanner.new(str)
obj = parse(scanner)
raise BdecodeError unless scanner.eos?
return obj
end
+ # Bdecodes the file located at +path+
def load_file(path)
load(File.open(path).read)
end
def parse(scanner) # :nodoc:
case token = scanner.scan(/[ild]|\d+:|\s/)
when nil
- raise BdecodeError, scanner.pos
+ raise BdecodeError
when "i"
number = scanner.scan(/0|(?:-?[1-9][0-9]*)/)
- unless number and scanner.scan(/e/)
- raise BdecodeError, scanner.pos
- end
+ raise BdecodeError unless number and scanner.scan(/e/)
return number.to_i
when "l"
ary = []
until scanner.peek(1) == "e"
ary.push(parse(scanner))
@@ -187,14 +213,11 @@
return ary
when "d"
hsh = {}
until scanner.peek(1) == "e"
key, value = parse(scanner), parse(scanner)
- unless key.is_a? String
- raise BdecodeError, "error at #{scanner.pos}: " +
- "key must be a string"
- end
+ raise BdecodeError, "key must be a string" unless key.is_a? String
hsh.store(key, value)
end
scanner.pos += 1
return hsh
when /\d+:/
@@ -203,10 +226,10 @@
scanner.pos += length
return str
when /\s/
nil
else
- raise BdecodeError, scanner.pos
+ raise BdecodeError
end
end
private :parse
end