bencoder 0.0.1 → 0.0.3

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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -0
  3. data/lib/bencoder.rb +121 -14
  4. data/test/test_bencoder.rb +27 -2
  5. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 09c62bd7987598ff7a2b4b56a1e69c24827c9f0b
4
- data.tar.gz: c15edd8914036432bdec89a8494349de123e11a1
3
+ metadata.gz: 51e49c375c750bc8fc138694c480243464b72569
4
+ data.tar.gz: 61d783b6a72ed79143a178e0b3238d66285174cb
5
5
  SHA512:
6
- metadata.gz: 49581f10345b062663e1030505a961b30229bfdc399c1c09cab863302264e8dafe81b610b273898b3c1589a29373572f8daa82014c80d8b66f6c58ccf72f2e2e
7
- data.tar.gz: aad379db9c60f0f096c0c3e3123d1d0ae92c9f66b02d6aa1744c39f358cb66c06c102cd9f2c6eb98f86867bce7f7307404623b4979e6d411fb54b10c7b4d7311
6
+ metadata.gz: 624aefbb8c412f1ad58f8df03a6a3492af110859065e7bff4541d286361e6bee0113fbc0fdbfa388f5c183e4c4b036080fefe036bcdba4cfc08341384fa9b17d
7
+ data.tar.gz: 65232d1a24bfcb6cf2e5abea661df2fba8ff0a2441aacbe696fdb0417b8b0ff82a38cdddadaa7bf8058ffeee74c563648b5537b0ab45b866d20d67af39338724
data/README.md CHANGED
@@ -3,6 +3,15 @@ bencoder
3
3
 
4
4
  Bittorrent encoding in ruby
5
5
 
6
+ BEncoder will encode the 4 data types in the specification:
7
+
8
+ - Strings
9
+ - Integers
10
+ - Arrays
11
+ - Hashes
12
+
13
+ Additionally, it will pass symbols as strings, to allow for easier hash convertion.
14
+
6
15
  install with
7
16
 
8
17
  gem install bencoder
@@ -13,7 +22,13 @@ Usage is easy:
13
22
  BEncoder.encode "herp"
14
23
  => "4:herp"
15
24
 
25
+ BEncoder.decode "4:herp"
26
+ => "herp"
27
+
16
28
  BEncoder.encode ['what', 'strange', { data: 'I', have: 'here' }, 666]
17
29
  => "l4:what7:stranged4:data1:I4:have4:hereei666ee"
30
+
31
+ BEncoder.decode 'l4:what7:stranged4:data1:I4:have4:hereei666ee'
32
+ => ['what', 'strange', { data: 'I', have: 'here' }, 666]
18
33
  ```
19
34
  Intentionally minimalistic.
data/lib/bencoder.rb CHANGED
@@ -1,18 +1,125 @@
1
+ require 'stringio'
1
2
  class BEncoder
2
- def self.encode(object)
3
- case object
4
- when Symbol
5
- encode object.to_s
6
- when String
7
- "#{object.length}:#{object}"
8
- when Integer
9
- "i#{object}e"
10
- when Array
11
- encoded_content = object.inject("l") { |result, el| result += encode(el) }
12
- encoded_content += "e"
13
- when Hash
14
- encoded = object.inject("d") { |result, (k,v)| result += "#{encode(k.to_s)}#{encode(v)}" }
15
- encoded += "e"
3
+ class << self
4
+ def encode(object)
5
+ case object
6
+ when Symbol
7
+ encode object.to_s
8
+ when String
9
+ encode_string object
10
+ when Integer
11
+ encode_int object
12
+ when Array
13
+ encode_array object
14
+ when Hash
15
+ encode_hash object
16
+ end
17
+ end
18
+
19
+ def decode(string)
20
+ parse string
21
+ end
22
+
23
+
24
+
25
+ private
26
+
27
+ def parse(string)
28
+ case string[0]
29
+ when 'i'
30
+ parse_int string
31
+ when 'l'
32
+ parse_list string
33
+ when 'd'
34
+ parse_dict string
35
+ else
36
+ parse_string string
37
+ end
38
+ end
39
+
40
+ def parse_list(string)
41
+ if string.is_a? StringIO
42
+ str = string
43
+ str.getc if peek(str) == 'l'
44
+ elsif string[0] == 'l' && string[-1] == 'e'
45
+ str = StringIO.new string[1..-2]
46
+ else
47
+ raise 'Not a list'
48
+ end
49
+ list = []
50
+ until peek(str) == 'e' || str.eof?
51
+ case peek(str)
52
+ when 'i'
53
+ list << parse_int(str.gets sep='e')
54
+ when 'l'
55
+ list << parse_list(str)
56
+ when 'd'
57
+ list << parse_dict(str)
58
+ when ->(e) { e =~ /\d/ }
59
+ length = str.gets(sep=':').to_i
60
+ list << str.gets(length)
61
+ else
62
+ raise str.read
63
+ end
64
+ end
65
+ str.getc
66
+ list
67
+ end
68
+
69
+ def parse_dict(string)
70
+ if string.is_a? StringIO
71
+ string.getc if peek(string) == 'd'
72
+ list_of_keys_and_values = parse_list(string)
73
+ elsif string[0] == 'd' && string[-1] == 'e'
74
+ list_of_keys_and_values = parse_list("l#{string[1..-2]}e")
75
+ else
76
+ raise 'Something in hash is wrong!'
77
+ end
78
+ hash = {}
79
+ list_of_keys_and_values.each_slice(2) do |k,v|
80
+ hash[k] = v
81
+ end
82
+ hash
83
+ end
84
+
85
+ def parse_int(string)
86
+ if string[0] == 'i' && string[-1] == 'e'
87
+ string[1..-2].to_i
88
+ else
89
+ raise 'Int is formatted wrong'
90
+ end
91
+ end
92
+
93
+ def parse_string(string)
94
+ length, content = string.split ':'
95
+ if content.length == length.to_i
96
+ content
97
+ else
98
+ raise 'String length is messed up'
99
+ end
100
+ end
101
+
102
+ def encode_string(string)
103
+ "#{string.length}:#{string}"
104
+ end
105
+
106
+ def encode_int(int)
107
+ "i#{int}e"
108
+ end
109
+
110
+ def encode_array(array)
111
+ array.inject("l") { |result, el| result += encode(el) } + "e"
112
+ end
113
+
114
+ def encode_hash(hash)
115
+ hash.inject("d") { |result, (k,v)| result += "#{encode(k.to_s)}#{encode(v)}" } + 'e'
116
+ end
117
+
118
+ def peek(io)
119
+ char = io.getc
120
+ io.ungetc char
121
+ puts char
122
+ char
16
123
  end
17
124
  end
18
125
  end
@@ -1,10 +1,13 @@
1
1
  require 'minitest/autorun'
2
2
  require 'bencoder'
3
3
 
4
- class TestBencoder < Minitest::Unit::TestCase
4
+ class TestBencoder < Minitest::Test
5
5
  def setup
6
6
  @be = BEncoder
7
7
  end
8
+
9
+ #encoding
10
+
8
11
  def test_string_encoding
9
12
  assert_equal '7:Someday', @be.encode('Someday')
10
13
  end
@@ -21,7 +24,29 @@ class TestBencoder < Minitest::Unit::TestCase
21
24
  assert_equal 'd4:what2:is2:up4:dawge', @be.encode({what: 'is', up: 'dawg'})
22
25
  end
23
26
 
24
- def test_nested_values
27
+ def test_nested_encoding
25
28
  assert_equal 'ld4:somel5:times3:youe5:gotta3:let2:go1:!ei2e5:wooooli1e1:21:3ee', @be.encode([{'some' => ['times', 'you'], gotta: 'let', go: '!'}, 2, "woooo", [1, '2', "3"]])
26
29
  end
30
+
31
+ #decoding
32
+
33
+ def test_string_decoding
34
+ assert_equal "I'm free!", @be.decode("9:I'm free!")
35
+ end
36
+
37
+ def test_int_decoding
38
+ assert_equal 321, @be.decode('i321e')
39
+ end
40
+
41
+ def test_array_decoding
42
+ assert_equal ['1', 2, 3], @be.decode('l1:1i2ei3ee')
43
+ end
44
+
45
+ def test_hash_decoding
46
+ assert_equal({'abc' => 'def', 'ghi' => 32}, @be.decode("d3:abc3:def3:ghii32ee"))
47
+ end
48
+
49
+ def test_nested_decoding
50
+ assert_equal [{'some' => ['times', 'you'], 'gotta' => 'let', 'go' => '!'}, 2, "woooo", [1, '2', "3"]], @be.decode('ld4:somel5:times3:youe5:gotta3:let2:go1:!ei2e5:wooooli1e1:21:3ee')
51
+ end
27
52
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bencoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Holbek Jensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-13 00:00:00.000000000 Z
11
+ date: 2014-10-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Minimalistic bencoder gem
13
+ description: Minimalistic BEncoding gem
14
14
  email: kholbekj@gmail.com
15
15
  executables: []
16
16
  extensions: []