bencode 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ doc
2
+ *.gem
3
+ .idea
data/README.md CHANGED
@@ -22,12 +22,17 @@ It contains only four data types, namely:
22
22
  Examples
23
23
  --------
24
24
 
25
+ Encoding objects is as simple as calling `#bencode` on them:
26
+
25
27
  "foo bar".bencode # => "7:foo bar"
26
28
  42.bencode # => "i42e"
27
29
  [1, 2, 3].bencode # => "li1ei2ei3ee"
28
30
  {"foo" => 1, "bar" => -10}.bencode # => "d3:bari-10e3:fooi1ee"
29
31
 
30
32
 
33
+ Decoding a data stream is as easy as calling `BEncode.load(data)`.
34
+
35
+
31
36
  License
32
37
  -------
33
38
 
@@ -37,4 +42,8 @@ Released under the MIT license.
37
42
  Contributors
38
43
  ------------
39
44
 
45
+ - Daniel Schierbeck
40
46
  - Mike Hodgson
47
+ - Andrew Danforth
48
+ - Eric Himmelreich
49
+ - Allen Madsen
data/Rakefile CHANGED
@@ -2,13 +2,41 @@
2
2
  require 'rake/testtask'
3
3
  require 'rake/rdoctask'
4
4
 
5
- ##
6
- # Run all unit tests.
7
- Rake::TestTask.new
5
+ task :default => :test
6
+
7
+ desc "Run all unit tests"
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'lib' << 'test'
10
+ test.pattern = 'test/**/*_test.rb'
11
+ test.verbose = false
12
+ end
8
13
 
9
14
 
10
- ##
11
- # Generate RDoc documentation.
15
+ desc "Generate RDoc documentation"
12
16
  Rake::RDocTask.new :doc do |rdoc|
13
17
  rdoc.rdoc_dir = 'doc'
14
18
  end
19
+
20
+ desc "Run all the benchmarks"
21
+ task :benchmark do
22
+ Dir["test/benchmark/*.rb"].each do |file|
23
+ puts ">> Running #{file}"
24
+ puts %x[ruby #{file}]
25
+ puts
26
+ end
27
+ end
28
+
29
+ begin
30
+ require 'jeweler'
31
+ Jeweler::Tasks.new do |gem|
32
+ gem.name = "bencode"
33
+ gem.summary = "Encode and decode bencoded data"
34
+ gem.description = "A simple encoder and decoder for the BitTorrent serialization format."
35
+ gem.email = "daniel.schierbeck@gmail.com"
36
+ gem.homepage = "http://github.com/dasch/ruby-bencode"
37
+ gem.authors = ["Daniel Schierbeck"]
38
+ end
39
+ Jeweler::GemcutterTasks.new
40
+ rescue LoadError
41
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.0
@@ -1,4 +1,6 @@
1
1
 
2
+ require 'strscan'
3
+
2
4
  module BEncode
3
5
  class << self
4
6
  # BEncodes +obj+
@@ -8,8 +10,6 @@ module BEncode
8
10
 
9
11
  # Bdecodes +str+
10
12
  def load(str)
11
- require 'strscan'
12
-
13
13
  scanner = StringScanner.new(str)
14
14
  obj = parse(scanner)
15
15
  raise BEncode::DecodeError unless scanner.eos?
@@ -18,51 +18,48 @@ module BEncode
18
18
 
19
19
  # Bdecodes the file located at +path+
20
20
  def load_file(path)
21
- if RUBY_PLATFORM =~ /(win|w)32$/
22
- load(File.open(path, 'rb').read)
23
- else
24
- load(File.open(path).read)
25
- end
21
+ load(File.open(path, 'rb') {|f| f.read})
26
22
  end
27
23
 
28
24
  def parse(scanner) # :nodoc:
29
- case scanner.scan(/[ild]|\d+:/)
30
- when "i"
31
- number = scanner.scan(/0|(?:-?[1-9][0-9]*)/)
32
- raise BEncode::DecodeError unless number and scanner.scan(/e/)
33
- return number.to_i
34
- when "l"
35
- ary = []
36
- # TODO: There must be a smarter way of doing this...
37
- ary.push(parse(scanner)) until scanner.peek(1) == "e"
25
+ case scanner.peek(1)[0]
26
+ when ?i
38
27
  scanner.pos += 1
28
+ num = scanner.scan_until(/e/) or raise BEncode::DecodeError
29
+ return Integer(num.chop)
30
+ when ?l
31
+ scanner.pos += 1
32
+ ary = []
33
+ ary.push(parse(scanner)) until scanner.scan(/e/)
39
34
  return ary
40
- when "d"
35
+ when ?d
36
+ scanner.pos += 1
41
37
  hsh = {}
42
- until scanner.peek(1) == "e"
43
- key, value = parse(scanner), parse(scanner)
38
+ until scanner.scan(/e/)
39
+ key = parse(scanner)
44
40
 
45
- unless key.is_a? String
46
- raise BEncode::DecodeError, "key must be a string"
41
+ unless key.is_a? String or key.is_a? Fixnum
42
+ raise BEncode::DecodeError, "key must be a string or number"
47
43
  end
48
44
 
49
- hsh.store(key, value)
45
+ hsh.store(key.to_s, parse(scanner))
50
46
  end
51
- scanner.pos += 1
52
47
  return hsh
53
- when /\d+:/
54
- length = Integer($~.string.chop)
55
- str = scanner.peek(length)
48
+ when ?0 .. ?9
49
+ num = scanner.scan_until(/:/) or
50
+ raise BEncode::DecodeError, "invalid string length (no colon)"
56
51
 
57
52
  begin
53
+ length = Integer(num.chop)
54
+ str = scanner.peek(length)
58
55
  scanner.pos += length
59
- rescue RangeError
56
+ rescue
60
57
  raise BEncode::DecodeError, "invalid string length"
61
58
  end
62
59
 
63
60
  return str
64
61
  else
65
- raise BEncode::DecodeError
62
+ raise BEncode::DecodeError, "Invalid specifier #{scanner.peek(1).inspect} at position #{scanner.pos+1}"
66
63
  end
67
64
  end
68
65
 
data/lib/bencode/io.rb CHANGED
@@ -1,11 +1,11 @@
1
1
 
2
2
  class IO
3
3
  def self.bdecode(filename)
4
- open(filename, 'r').bdecode
4
+ open(filename, 'rb') {|io| io.bdecode}
5
5
  end
6
6
 
7
7
  def self.bencode(filename)
8
- open(filename, 'r').bencode
8
+ open(filename, 'rb') {|io| io.bencode}
9
9
  end
10
10
 
11
11
  def bdecode
@@ -0,0 +1,22 @@
1
+ $:.unshift(File.dirname(__FILE__)+"/../../lib")
2
+ require 'benchmark'
3
+ require 'bencode'
4
+
5
+ Benchmark.bmbm do |x|
6
+ x.report("Decoding an integer") do
7
+ 100_000.times do
8
+ BEncode.load("i42e")
9
+ end
10
+ end
11
+
12
+ x.report("Decoding an string") do
13
+ 100_000.times do
14
+ BEncode.load("6:foobar")
15
+ end
16
+ end
17
+ x.report("Decoding a long integer array") do
18
+ 100.times do
19
+ BEncode.load("l" + ("i42e" * 1000) + "e")
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.dirname(__FILE__)+"/../../lib")
2
+ require 'benchmark'
3
+ require 'bencode'
4
+
5
+ Benchmark.bmbm do |x|
6
+ x.report("Encoding an array of integers") do
7
+ 100.times do
8
+ ((1..50).to_a * 100).bencode
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+
2
+ require 'test/environment'
3
+
4
+
5
+ class BitTorrentTest < Test::Unit::TestCase
6
+ should "load a bencoded torrent file" do
7
+ assert_nothing_raised do
8
+ BEncode.load_file("test/fixtures/python.torrent")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+
2
+ require 'test/environment'
3
+
4
+ class DecodingTest < Test::Unit::TestCase
5
+ context "The BEncode decoder" do
6
+ should_decode 42, "i42e"
7
+ should_decode 0, "i0e"
8
+ should_decode -42, "i-42e"
9
+
10
+ should_decode "foo", "3:foo"
11
+ should_decode "", "0:"
12
+
13
+ should_decode [1, 2, 3], "li1ei2ei3ee"
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+
2
+ require 'test/environment'
3
+
4
+ class EncodingTest < Test::Unit::TestCase
5
+ context "The BEncode encoder" do
6
+ should_encode "i42e", 42
7
+ should_encode "3:foo", "foo"
8
+ end
9
+ end
data/test/environment.rb CHANGED
@@ -1,2 +1,8 @@
1
1
 
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'shoulda'
2
5
  require File.dirname(__FILE__) + '/../lib/bencode'
6
+ Dir.glob(File.dirname(__FILE__) + '/shoulda_macros/*.rb').each do |macro|
7
+ require macro
8
+ end
Binary file
@@ -0,0 +1,8 @@
1
+
2
+ class Test::Unit::TestCase
3
+ def self.should_decode(expected, encoded)
4
+ should "decode #{encoded.inspect} into #{expected.inspect}" do
5
+ assert_equal expected, BEncode.load(encoded)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+
2
+ class Test::Unit::TestCase
3
+ def self.should_encode(expected, value)
4
+ should "encode #{value.inspect} into #{expected.inspect}" do
5
+ assert_equal expected, value.bencode
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+
2
+ require 'test/environment'
3
+
4
+ class UTF8DecodingTest < Test::Unit::TestCase
5
+ context "The BEncode decoder" do
6
+ should "be able to handle UTF8-encoded data" do
7
+ assert_nothing_raised do
8
+ BEncode.load_file('test/fixtures/test.torrent')
9
+ end
10
+ end
11
+ end
12
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bencode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schierbeck
@@ -9,39 +9,53 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-06 00:00:00 +02:00
12
+ date: 2010-02-06 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: Ruby bindings for the bencode data serialization format.
16
+ description: A simple encoder and decoder for the BitTorrent serialization format.
17
17
  email: daniel.schierbeck@gmail.com
18
18
  executables: []
19
19
 
20
20
  extensions: []
21
21
 
22
- extra_rdoc_files: []
23
-
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.md
24
25
  files:
25
- - Rakefile
26
+ - .gitignore
26
27
  - LICENSE
27
28
  - README.md
29
+ - Rakefile
30
+ - VERSION
28
31
  - lib/bencode.rb
29
32
  - lib/bencode/decode.rb
30
33
  - lib/bencode/decode_error.rb
31
- - lib/bencode/encode_error.rb
32
- - lib/bencode/io.rb
33
34
  - lib/bencode/encode/array.rb
34
- - lib/bencode/encode/integer.rb
35
- - lib/bencode/encode/string.rb
36
35
  - lib/bencode/encode/hash.rb
36
+ - lib/bencode/encode/integer.rb
37
37
  - lib/bencode/encode/object.rb
38
+ - lib/bencode/encode/string.rb
39
+ - lib/bencode/encode_error.rb
40
+ - lib/bencode/io.rb
41
+ - test/benchmark/decoding.rb
42
+ - test/benchmark/encoding.rb
43
+ - test/bittorrent_test.rb
44
+ - test/decoding_test.rb
45
+ - test/encoding_test.rb
46
+ - test/environment.rb
47
+ - test/fixtures/python.torrent
48
+ - test/fixtures/test.torrent
49
+ - test/shoulda_macros/decoding.rb
50
+ - test/shoulda_macros/encoding.rb
51
+ - test/utf8_decoding_test.rb
38
52
  has_rdoc: true
39
- homepage: http://github.com/dasch/ruby-bencode-bindings
53
+ homepage: http://github.com/dasch/ruby-bencode
40
54
  licenses: []
41
55
 
42
56
  post_install_message:
43
- rdoc_options: []
44
-
57
+ rdoc_options:
58
+ - --charset=UTF-8
45
59
  require_paths:
46
60
  - lib
47
61
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -62,8 +76,14 @@ rubyforge_project:
62
76
  rubygems_version: 1.3.5
63
77
  signing_key:
64
78
  specification_version: 3
65
- summary: Ruby bencode bindings
79
+ summary: Encode and decode bencoded data
66
80
  test_files:
67
- - test/test_decode_utf8.rb
81
+ - test/bittorrent_test.rb
82
+ - test/decoding_test.rb
83
+ - test/utf8_decoding_test.rb
84
+ - test/shoulda_macros/decoding.rb
85
+ - test/shoulda_macros/encoding.rb
68
86
  - test/environment.rb
69
- - test/fixtures/test.torrent
87
+ - test/encoding_test.rb
88
+ - test/benchmark/decoding.rb
89
+ - test/benchmark/encoding.rb
@@ -1,13 +0,0 @@
1
-
2
- require 'test/unit'
3
- require 'test/environment'
4
-
5
- class TestDecodeUTF8 < Test::Unit::TestCase
6
-
7
- def test_can_handle_utf8_encoded_data
8
- assert_nothing_raised do
9
- BEncode.load_file('test/fixtures/test.torrent')
10
- end
11
- end
12
-
13
- end