bencodr 1.2.0 → 2.0.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/.autotest +0 -0
- data/.document +0 -0
- data/.gitignore +3 -1
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/LICENSE +0 -0
- data/{README.rdoc → README.md} +88 -53
- data/Rakefile +4 -44
- data/bencodr.gemspec +18 -75
- data/lib/bencodr.rb +23 -40
- data/lib/bencodr/dictionary.rb +19 -47
- data/lib/bencodr/ext.rb +38 -0
- data/lib/bencodr/integer.rb +17 -47
- data/lib/bencodr/io.rb +21 -56
- data/lib/bencodr/list.rb +19 -45
- data/lib/bencodr/object.rb +36 -0
- data/lib/bencodr/parser.rb +0 -14
- data/lib/bencodr/string.rb +17 -46
- data/lib/bencodr/version.rb +3 -0
- data/spec/bencode_spec.rb +17 -22
- data/spec/bencodr/dictionary_spec.rb +1 -74
- data/spec/bencodr/ext_spec.rb +66 -0
- data/spec/bencodr/integer_spec.rb +1 -67
- data/spec/bencodr/io_spec.rb +28 -30
- data/spec/bencodr/list_spec.rb +1 -31
- data/spec/bencodr/object_spec.rb +9 -0
- data/spec/bencodr/parser_spec.rb +38 -173
- data/spec/bencodr/string_spec.rb +1 -68
- data/spec/custom_matchers.rb +87 -0
- data/spec/samples/bencode.rb.torrent +0 -0
- data/spec/samples/mini.bencode +0 -0
- data/spec/samples/python.torrent +0 -0
- data/spec/shared_examples.rb +91 -0
- data/spec/spec_helper.rb +8 -9
- metadata +55 -28
- data/VERSION +0 -1
- data/autotest/discover.rb +0 -3
- data/spec/spec.opts +0 -1
data/.autotest
CHANGED
File without changes
|
data/.document
CHANGED
File without changes
|
data/.gitignore
CHANGED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create use 1.9.2@bencodr
|
data/Gemfile
ADDED
data/LICENSE
CHANGED
File without changes
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,31 +1,70 @@
|
|
1
|
-
|
2
|
-
*
|
3
|
-
*
|
4
|
-
*
|
5
|
-
*
|
6
|
-
*
|
7
|
-
|
8
|
-
|
9
|
-
== Synopsis
|
1
|
+
# BEncodr
|
2
|
+
* **Author** Allen Madsen (blatyo)
|
3
|
+
* **My Site** http://www.allenmadsen.com
|
4
|
+
* **Gem** http://gemcutter.org/gems/bencodr
|
5
|
+
* **Source** http://github.com/blatyo/bencodr
|
6
|
+
* **Issue Tracker** http://github.com/blatyo/bencodr/issues
|
7
|
+
|
8
|
+
## Synopsis
|
10
9
|
This gem provides a way to encode and parse bencodings used by the Bit Torrent protocol.
|
11
10
|
|
12
|
-
|
11
|
+
## Installation
|
13
12
|
|
14
|
-
|
15
|
-
> [sudo] gem install bencodr
|
16
|
-
Successfully installed bencodr
|
17
|
-
1 gem installed
|
18
|
-
Installing ri documentation for bencodr...
|
19
|
-
Building YARD (yri) index for bencodr...
|
20
|
-
Installing RDoc documentation for bencodr
|
13
|
+
Install the gem:
|
21
14
|
|
22
|
-
|
15
|
+
``` bash
|
16
|
+
gem install bencodr
|
17
|
+
```
|
18
|
+
|
19
|
+
Require it in your ruby files:
|
20
|
+
|
21
|
+
``` ruby
|
23
22
|
require 'bencodr'
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
### BEncodr
|
27
|
+
Most of the functionality of this library can be accessed directly on the BEncodr class.
|
28
|
+
|
29
|
+
``` ruby
|
30
|
+
# encoding is just like calling bencode on the object
|
31
|
+
BEncodr.bencode("string") #=> "6:string"
|
24
32
|
|
25
|
-
|
26
|
-
|
33
|
+
# decoding is just like calling bdecode on a bencoding
|
34
|
+
BEncodr.bdecode("6:string") #=> "string"
|
35
|
+
|
36
|
+
# you can work directly with files too
|
37
|
+
BEncodr.bencode_file("my_awesome.torrent", {:announce => "http://www.sometracker.com/announce:80"})
|
38
|
+
BEncodr.bdecode_file("my_awesome.torrent") #=> {:announce => "http://www.sometracker.com/announce:80"}
|
39
|
+
```
|
40
|
+
|
41
|
+
### Monkey Patching
|
42
|
+
In order to get this functionality on the objects described below, you can call:
|
43
|
+
|
44
|
+
``` ruby
|
45
|
+
BEncodr.include!
|
46
|
+
```
|
47
|
+
|
48
|
+
This will extend:
|
49
|
+
|
50
|
+
* BEncodr::String
|
51
|
+
* String
|
52
|
+
* Symbol
|
53
|
+
* URI::Generic
|
54
|
+
* BEncodr::Integer
|
55
|
+
* Numeric
|
56
|
+
* Time
|
57
|
+
* BEncodr::List
|
58
|
+
* Array
|
59
|
+
* BEncodr::Dictionary
|
60
|
+
* Hash
|
61
|
+
* BEncodr::IO
|
62
|
+
* IO
|
63
|
+
|
64
|
+
### String
|
27
65
|
BEncoded strings are length-prefixed base ten followed by a colon and the string.
|
28
66
|
|
67
|
+
``` ruby
|
29
68
|
# strings
|
30
69
|
"".bencode #=> "0:"
|
31
70
|
"string".bencode #=> "6:string"
|
@@ -36,10 +75,12 @@ BEncoded strings are length-prefixed base ten followed by a colon and the string
|
|
36
75
|
# URIs
|
37
76
|
uri = URI.parse("http://github.com/blatyo/bencode")
|
38
77
|
uri.bencode #=> "32:http://github.com/blatyo/bencode"
|
78
|
+
```
|
39
79
|
|
40
|
-
|
80
|
+
### Integer
|
41
81
|
Bencoded integers are represented by an 'i' followed by the number in base 10 followed by an 'e'.
|
42
82
|
|
83
|
+
``` ruby
|
43
84
|
# integers
|
44
85
|
1.bencode #=> "i1e"
|
45
86
|
-1.bencode #=> "i-1e"
|
@@ -51,18 +92,22 @@ Bencoded integers are represented by an 'i' followed by the number in base 10 fo
|
|
51
92
|
|
52
93
|
# times
|
53
94
|
Time.at(4).bencode #=> "i4e"
|
95
|
+
```
|
54
96
|
|
55
|
-
|
97
|
+
### List
|
56
98
|
Bencoded lists are encoded as an 'l' followed by their elements (also bencoded) followed by an 'e'.
|
57
99
|
|
100
|
+
``` ruby
|
58
101
|
# arrays
|
59
102
|
[].bencode #=> "le"
|
60
103
|
[:e, "a", 1, Time.at(11)].bencode #=> "l1:e1:ai1ei11ee"
|
104
|
+
```
|
61
105
|
|
62
|
-
|
106
|
+
### Dictionary
|
63
107
|
Bencoded dictionaries are encoded as a 'd' followed by a list of alternating keys and their corresponding values
|
64
108
|
followed by an 'e'. Keys appear in sorted order (sorted as raw strings, not alphanumerics) and are always strings.
|
65
109
|
|
110
|
+
``` ruby
|
66
111
|
# hashes
|
67
112
|
{}.bencode #=> "de"
|
68
113
|
{"string" => "string"}.bencode #=> "d6:string6:stringe"
|
@@ -79,18 +124,22 @@ followed by an 'e'. Keys appear in sorted order (sorted as raw strings, not alph
|
|
79
124
|
|
80
125
|
# Note: keys are sorted as raw strings.
|
81
126
|
{:a => 1, "A" => 1, 1=> 1}.bencode #=> "d1:1i1e1:Ai1e1:ai1ee"
|
127
|
+
```
|
82
128
|
|
83
|
-
|
129
|
+
### Decoding
|
84
130
|
You can decode a bencoding by calling bdecode on the string.
|
85
131
|
|
132
|
+
``` ruby
|
86
133
|
"6:string".bdecode #=> "string"
|
87
134
|
"i1e".bdecode #=> 1
|
88
135
|
"le".bdecode #=> []
|
89
136
|
"de".bdecode #=> {}
|
137
|
+
```
|
90
138
|
|
91
|
-
|
139
|
+
### IO and Files
|
92
140
|
You can also write and read bencodings.
|
93
141
|
|
142
|
+
``` ruby
|
94
143
|
# write to standard out
|
95
144
|
IO.bencode(1, "string") #=> "6:string" to stdout
|
96
145
|
$stdout.bencode("string") #=> "6:string" to stdout
|
@@ -110,58 +159,44 @@ You can also write and read bencodings.
|
|
110
159
|
|
111
160
|
file = File.open("a.bencode", "wb")
|
112
161
|
file.bdecode #=> "string"
|
162
|
+
```
|
113
163
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
# encoding is just like calling bencode on the object
|
118
|
-
BEncodr.encode("string") #=> "6:string"
|
119
|
-
|
120
|
-
# decoding is just like calling bdecode on a bencoding
|
121
|
-
BEncodr.decode("6:string") #=> "string"
|
122
|
-
|
123
|
-
# you can work directly with files too
|
124
|
-
BEncodr.encode_file("my_awesome.torrent", {:announce => "http://www.sometracker.com/announce:80"})
|
125
|
-
BEncodr.decode_file("my_awesome.torrent") #=> {:announce => "http://www.sometracker.com/announce:80"}
|
126
|
-
|
127
|
-
=== Registering Types
|
128
|
-
When using bencodings it may be useful to translate your own objects into bencoded strings. You can do that with the
|
129
|
-
register methods on each BEncode type. All register does is define a bencode instance method for the class that
|
130
|
-
internally uses type conversion. That means if you want to specify a String type then your class must have a to_s or
|
131
|
-
to_str instance method. The same goes for all the other types.
|
132
|
-
|
133
|
-
Keep in mind when registering that if you register a class for two separate types it will only retain the bencode method
|
134
|
-
of the last type registered for.
|
164
|
+
### Make Your Own Objects Compatible
|
165
|
+
When using bencodings it may be useful to translate your own objects into bencoded strings.
|
135
166
|
|
167
|
+
``` ruby
|
136
168
|
# register string type
|
137
|
-
BEncodr::String
|
169
|
+
Range.send :include, BEncodr::String
|
138
170
|
(1..2).bencode #=> "4:1..2"
|
139
171
|
|
140
172
|
# register integer type
|
141
|
-
BEncodr::Integer
|
173
|
+
NilClass.send :include, BEncodr::Integer
|
142
174
|
nil.bencode #=> "i0e"
|
143
175
|
|
144
176
|
# register list type
|
145
|
-
BEncodr::List
|
177
|
+
Range.send :include, BEncodr::List
|
146
178
|
(1..2).bencode #=> "li1ei2ee"
|
147
179
|
|
148
180
|
#register dictionary type
|
149
181
|
MyClass = Class.new do
|
182
|
+
include BEncodr::Dictionary
|
183
|
+
|
150
184
|
def to_h
|
151
185
|
{:a => "a", :b => "b"}
|
152
186
|
end
|
153
187
|
end
|
154
|
-
|
188
|
+
|
155
189
|
MyClass.new.bencode #=> "d1:a1:a1:b1:be"
|
190
|
+
```
|
156
191
|
|
157
|
-
|
192
|
+
## Note on Reporting Issues
|
158
193
|
|
159
194
|
* Try to make a failing test case
|
160
195
|
* Tell me which version of ruby you're using
|
161
196
|
* Tell me which OS you are using
|
162
197
|
* Provide me with any extra files if necessary
|
163
198
|
|
164
|
-
|
199
|
+
## Note on Patches/Pull Requests
|
165
200
|
|
166
201
|
* Fork the project.
|
167
202
|
* Make your feature addition or bug fix.
|
@@ -171,6 +206,6 @@ of the last type registered for.
|
|
171
206
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
172
207
|
* Send me a pull request. Bonus points for topic branches.
|
173
208
|
|
174
|
-
|
209
|
+
## Copyright
|
175
210
|
|
176
211
|
Copyright (c) 2010 Allen Madsen. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,45 +1,5 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "bencodr"
|
8
|
-
gem.summary = "This gem provides a way to encode and parse bencodings used by the Bit Torrent protocol."
|
9
|
-
gem.description = "This gem provides a way to encode and parse bencodings used by the Bit Torrent protocol."
|
10
|
-
gem.email = "blatyo@gmail.com"
|
11
|
-
gem.homepage = "http://github.com/blatyo/bencodr"
|
12
|
-
gem.authors = ["Allen Madsen"]
|
13
|
-
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
-
gem.add_development_dependency "yard", ">= 0"
|
15
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
-
end
|
17
|
-
Jeweler::GemcutterTasks.new
|
18
|
-
rescue LoadError
|
19
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
-
end
|
21
|
-
|
22
|
-
require 'spec/rake/spectask'
|
23
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
-
spec.libs << 'lib' << 'spec'
|
25
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
-
end
|
27
|
-
|
28
|
-
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
|
-
spec.libs << 'lib' << 'spec'
|
30
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
-
spec.rcov = true
|
32
|
-
end
|
33
|
-
|
34
|
-
task :spec => :check_dependencies
|
35
|
-
|
36
|
-
task :default => :spec
|
37
|
-
|
38
|
-
begin
|
39
|
-
require 'yard'
|
40
|
-
YARD::Rake::YardocTask.new
|
41
|
-
rescue LoadError
|
42
|
-
task :yardoc do
|
43
|
-
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
44
|
-
end
|
45
|
-
end
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
data/bencodr.gemspec
CHANGED
@@ -1,81 +1,24 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bencodr/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
6
|
+
s.name = "bencodr"
|
7
|
+
s.version = BEncodr::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Allen Madsen"]
|
10
|
+
s.email = ["blatyo@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/blatyo/bencodr"
|
12
|
+
s.summary = "This gem provides a way to encode and decode bencode used by the Bit Torrent protocol."
|
13
|
+
s.description = "This gem provides a way to encode and decode bencode used by the Bit Torrent protocol. Normal ruby objects can be marshalled as bencode and demarshalled back to ruby."
|
9
14
|
|
10
|
-
s.required_rubygems_version =
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
s.email = %q{blatyo@gmail.com}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE",
|
17
|
-
"README.rdoc"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".autotest",
|
21
|
-
".document",
|
22
|
-
".gitignore",
|
23
|
-
"LICENSE",
|
24
|
-
"README.rdoc",
|
25
|
-
"Rakefile",
|
26
|
-
"VERSION",
|
27
|
-
"autotest/discover.rb",
|
28
|
-
"bencodr.gemspec",
|
29
|
-
"lib/bencodr.rb",
|
30
|
-
"lib/bencodr/dictionary.rb",
|
31
|
-
"lib/bencodr/integer.rb",
|
32
|
-
"lib/bencodr/io.rb",
|
33
|
-
"lib/bencodr/list.rb",
|
34
|
-
"lib/bencodr/parser.rb",
|
35
|
-
"lib/bencodr/string.rb",
|
36
|
-
"spec/bencode_spec.rb",
|
37
|
-
"spec/bencodr/dictionary_spec.rb",
|
38
|
-
"spec/bencodr/integer_spec.rb",
|
39
|
-
"spec/bencodr/io_spec.rb",
|
40
|
-
"spec/bencodr/list_spec.rb",
|
41
|
-
"spec/bencodr/parser_spec.rb",
|
42
|
-
"spec/bencodr/string_spec.rb",
|
43
|
-
"spec/samples/bencode.rb.torrent",
|
44
|
-
"spec/samples/mini.bencode",
|
45
|
-
"spec/samples/python.torrent",
|
46
|
-
"spec/spec.opts",
|
47
|
-
"spec/spec_helper.rb"
|
48
|
-
]
|
49
|
-
s.homepage = %q{http://github.com/blatyo/bencodr}
|
50
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
51
|
-
s.require_paths = ["lib"]
|
52
|
-
s.rubygems_version = %q{1.3.5}
|
53
|
-
s.summary = %q{This gem provides a way to encode and parse bencodings used by the Bit Torrent protocol.}
|
54
|
-
s.test_files = [
|
55
|
-
"spec/bencode_spec.rb",
|
56
|
-
"spec/bencodr/dictionary_spec.rb",
|
57
|
-
"spec/bencodr/integer_spec.rb",
|
58
|
-
"spec/bencodr/io_spec.rb",
|
59
|
-
"spec/bencodr/list_spec.rb",
|
60
|
-
"spec/bencodr/parser_spec.rb",
|
61
|
-
"spec/bencodr/string_spec.rb",
|
62
|
-
"spec/spec_helper.rb"
|
63
|
-
]
|
64
|
-
|
65
|
-
if s.respond_to? :specification_version then
|
66
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
67
|
-
s.specification_version = 3
|
15
|
+
s.required_rubygems_version = ">= 1.3.6"
|
16
|
+
s.add_development_dependency "rspec", "~> 2.1.0"
|
17
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
|
+
s.add_development_dependency "fuubar", ">= 0.0.1"
|
68
19
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
74
|
-
s.add_dependency(%q<yard>, [">= 0"])
|
75
|
-
end
|
76
|
-
else
|
77
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
78
|
-
s.add_dependency(%q<yard>, [">= 0"])
|
79
|
-
end
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
80
24
|
end
|
81
|
-
|
data/lib/bencodr.rb
CHANGED
@@ -1,56 +1,39 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
path = File.expand_path(File.dirname(__FILE__)) + "/bencodr"
|
3
|
+
path = File.expand_path(File.dirname(__FILE__)) + "/bencodr/"
|
4
4
|
|
5
|
-
require path + "
|
6
|
-
require path + "
|
7
|
-
require path + "
|
8
|
-
require path + "
|
9
|
-
require path + "
|
10
|
-
require path + "
|
5
|
+
require path + "string"
|
6
|
+
require path + "integer"
|
7
|
+
require path + "list"
|
8
|
+
require path + "dictionary"
|
9
|
+
require path + "object"
|
10
|
+
require path + "parser"
|
11
|
+
require path + "io"
|
12
|
+
require path + "ext"
|
13
|
+
require path + "version"
|
11
14
|
|
12
15
|
module BEncodr
|
13
16
|
class BEncodeError < StandardError; end
|
14
17
|
|
15
18
|
class << self
|
16
|
-
|
17
|
-
|
18
|
-
# BEncode.decode("6:string") #=> "string"
|
19
|
-
#
|
20
|
-
# @param [::String] string the bencoded string to decode
|
21
|
-
# @return [::String, ::Integer, ::Hash, ::Array] the decoded object
|
22
|
-
def decode(string)
|
23
|
-
string.bdecode
|
19
|
+
def bdecode(object)
|
20
|
+
BEncodr::Object.bdecode(object)
|
24
21
|
end
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
# BEncode.decode_file("simple.torrent") #=> "d8:announce32:http://www..."
|
29
|
-
#
|
30
|
-
# @param [::String] file the file to decode
|
31
|
-
# @return [::String, ::Integer, ::Hash, ::Array] the decoded object
|
32
|
-
def decode_file(name)
|
33
|
-
File.bdecode name
|
23
|
+
def bdecode_file(fd)
|
24
|
+
::File.open(fd, "rb") {|file| bdecode(file.read)}
|
34
25
|
end
|
35
26
|
|
36
|
-
|
37
|
-
|
38
|
-
# BEncode.encode("string") #=> "6:string"
|
39
|
-
#
|
40
|
-
# @param [#bencodr] object the object to encode
|
41
|
-
# @return [::String] the bencoded object
|
42
|
-
def encode(object)
|
43
|
-
object.bencode
|
27
|
+
def bencode(object)
|
28
|
+
BEncodr::Object.bencode(object)
|
44
29
|
end
|
45
30
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
def encode_file(name, object)
|
53
|
-
File.bencode name, object
|
31
|
+
def bencode_file(fd, object)
|
32
|
+
::File.open(fd, "wb") {|file| file.write(bencode(object))}
|
33
|
+
end
|
34
|
+
|
35
|
+
def include!
|
36
|
+
Ext.include!
|
54
37
|
end
|
55
38
|
end
|
56
|
-
end
|
39
|
+
end
|