mikehodgson-bencode 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+
2
+ Copyright (c) 2009 Daniel Schierbeck
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+
2
+ Rube bencode binding
3
+ ====================
4
+
5
+ This is a simple library for reading and writing bencoded data.
6
+
7
+
8
+ What is bencode?
9
+ ----------------
10
+
11
+ Bencode is a simple data serialization format used by the popular
12
+ [BitTorrent](http://bittorrent.org/) P2P file sharing system.
13
+
14
+ It contains only four data types, namely:
15
+ - byte strings
16
+ - integers
17
+ - lists
18
+ - dictionaries
19
+
20
+
21
+ Examples
22
+ --------
23
+
24
+ "foo bar".bencode # => "7:foo bar"
25
+ 42.bencode # => "i42e"
26
+ [1, 2, 3].bencode # => "li1ei2ei3ee"
27
+ {"foo" => 1, "bar" => -10}.bencode # => "d3:bari-10e3:fooi1ee"
28
+
29
+
30
+ License
31
+ -------
32
+
33
+ Released under the MIT license.
data/lib/bencode.rb ADDED
@@ -0,0 +1,9 @@
1
+
2
+ # TODO: Write some documentation here.
3
+ module BEncode
4
+ VERSION = '0.5.0'
5
+ end
6
+
7
+ glob = File.join(File.dirname(__FILE__), 'bencode/**/*.rb')
8
+
9
+ Dir[glob].sort.each{|file| require file }
@@ -0,0 +1,83 @@
1
+
2
+ module BEncode
3
+ class << self
4
+ # BEncodes +obj+
5
+ def dump(obj)
6
+ obj.bencode
7
+ end
8
+
9
+ # Bdecodes +str+
10
+ def load(str)
11
+ require 'strscan'
12
+
13
+ scanner = StringScanner.new(str)
14
+ obj = parse(scanner)
15
+ raise BEncode::DecodeError unless scanner.eos?
16
+ return obj
17
+ end
18
+
19
+ # Bdecodes the file located at +path+
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
26
+ end
27
+
28
+ 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"
38
+ scanner.pos += 1
39
+ return ary
40
+ when "d"
41
+ hsh = {}
42
+ until scanner.peek(1) == "e"
43
+ key, value = parse(scanner), parse(scanner)
44
+
45
+ unless key.is_a? String
46
+ raise BEncode::DecodeError, "key must be a string"
47
+ end
48
+
49
+ hsh.store(key, value)
50
+ end
51
+ scanner.pos += 1
52
+ return hsh
53
+ when /\d+:/
54
+ length = Integer($~.string.chop)
55
+ str = scanner.peek(length)
56
+
57
+ begin
58
+ scanner.pos += length
59
+ rescue RangeError
60
+ raise BEncode::DecodeError, "invalid string length"
61
+ end
62
+
63
+ return str
64
+ else
65
+ raise BEncode::DecodeError
66
+ end
67
+ end
68
+
69
+ private :parse
70
+ end
71
+ end
72
+
73
+ class String
74
+ #
75
+ # Bdecodes the String object and returns the data serialized
76
+ # through bencoding.
77
+ #
78
+ # "li1ei2ei3ee".bdecode #=> [1, 2, 3]
79
+ #
80
+ def bdecode
81
+ BEncode.load(self)
82
+ end
83
+ end
@@ -0,0 +1,4 @@
1
+
2
+ unless BEncode.const_defined? :DecodeError
3
+ BEncode::DecodeError = Class.new(StandardError)
4
+ end
@@ -0,0 +1,16 @@
1
+
2
+ class Array
3
+ #
4
+ # Bencodes the Array object. Bencoded arrays are represented as
5
+ # +lxe+, where +x+ is zero or more bencoded objects.
6
+ #
7
+ # [1, "foo"].bencode #=> "li1e3:fooe"
8
+ #
9
+ def bencode
10
+ begin
11
+ "l#{map{|obj| obj.bencode }.join('')}e"
12
+ rescue BEncode::EncodeError
13
+ raise BEncode::EncodeError, "array items must be encodable"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+
2
+ class Hash
3
+ #
4
+ # Bencodes the Hash object. Bencoded hashes are represented as
5
+ # +dxe+, where +x+ is zero or a power of two bencoded objects.
6
+ # each key is immediately followed by its associated value.
7
+ # All keys must be strings. The keys of the bencoded hash will
8
+ # be in lexicographical order.
9
+ def bencode
10
+ pairs = sort.map{|key, val| [key.to_str.bencode, val.bencode] }
11
+ "d#{pairs.join('')}e"
12
+ rescue NoMethodError => error
13
+ raise BEncode::EncodeError, "dictionary keys must be strings"
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+
2
+ class Integer
3
+ #
4
+ # Bencodes the Integer object. Bencoded integers are represented
5
+ # as +ixe+, where +x+ is the integer with an optional
6
+ # hyphen prepended, indicating negativity.
7
+ #
8
+ # 42.bencode #=> "i42e"
9
+ # -7.bencode #=> "i-7e"
10
+ def bencode
11
+ "i#{self}e"
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+
2
+ class Object
3
+ #
4
+ # Raises an exception. Subclasses of Object must themselves
5
+ # define meaningful #bencode methods.
6
+ def bencode
7
+ raise BEncode::EncodeError, "cannot bencode #{self.class}"
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+
2
+ class String
3
+ #
4
+ # Bencodes the String object. Bencoded strings are represented
5
+ # as <code>x</code>:<code>y</code>, where +y+ is the string and +x+
6
+ # is the length of the string.
7
+ #
8
+ # "foo".bencode #=> "3:foo"
9
+ # "".bencode #=> "0:"
10
+ #
11
+ def bencode
12
+ "#{length}:#{self}"
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+
2
+ unless BEncode.const_defined? :EncodeError
3
+ BEncode::EncodeError = Class.new(StandardError)
4
+ end
data/lib/bencode/io.rb ADDED
@@ -0,0 +1,18 @@
1
+
2
+ class IO
3
+ def self.bdecode(filename)
4
+ open(filename, 'r').bdecode
5
+ end
6
+
7
+ def self.bencode(filename)
8
+ open(filename, 'r').bencode
9
+ end
10
+
11
+ def bdecode
12
+ read.chomp.bdecode
13
+ end
14
+
15
+ def bencode
16
+ read.chomp.bencode
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+
2
+ require File.dirname(__FILE__) + '/../lib/bencode'
Binary file
@@ -0,0 +1,13 @@
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
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mikehodgson-bencode
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Schierbeck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Ruby bindings for the bencode data serialization format.
17
+ email: daniel.schierbeck@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - LICENSE
26
+ - README.md
27
+ - lib/bencode.rb
28
+ - lib/bencode/decode.rb
29
+ - lib/bencode/decode_error.rb
30
+ - lib/bencode/encode_error.rb
31
+ - lib/bencode/io.rb
32
+ - lib/bencode/encode/array.rb
33
+ - lib/bencode/encode/integer.rb
34
+ - lib/bencode/encode/string.rb
35
+ - lib/bencode/encode/hash.rb
36
+ - lib/bencode/encode/object.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/dasch/ruby-bencode-bindings
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.2.0
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: Ruby bencode bindings
63
+ test_files:
64
+ - test/test_decode_utf8.rb
65
+ - test/environment.rb
66
+ - test/fixtures/test.torrent