ml-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
File without changes
data/lib/ml-ruby.rb ADDED
@@ -0,0 +1 @@
1
+ require 'ml-ruby/ml_client'
@@ -0,0 +1,192 @@
1
+ # ml_ruby: Ruby Bindings for the ML-Donkey GUI protocol
2
+ # Copyright (C) 2008 Jens Herrmann
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'socket'
19
+ include Socket::Constants
20
+ require File.dirname(__FILE__) + '/ml_protocol'
21
+
22
+ module ML_ruby
23
+ class ML_client
24
+
25
+ PROTOCOL_VERSION= 41
26
+ MAX_OPCODE_SENT= 59
27
+ MAX_OPCODE_RCVD= 68
28
+
29
+ TIME_OUT= 10
30
+
31
+ # public methods
32
+
33
+ def initialize host='localhost', port=4001, user=nil, password=nil
34
+ @listener= []
35
+ @send_queue= []
36
+ # ML_payload_handler::Types.keys.each do |opcode|
37
+ # add_listener opcode, self, :log
38
+ # end
39
+ connect host, port, user, password
40
+ end
41
+
42
+ def get_current_downloads
43
+ send_payload= ML_S_get_downloading_files.new( {} )
44
+ recv_payload= ML_R_downloading_files
45
+ send_and_wait_for send_payload, recv_payload
46
+ end
47
+
48
+ def get_finished_downloads
49
+ send_payload= ML_S_get_downloaded_files.new( {} )
50
+ recv_payload= ML_R_downloaded_files
51
+ send_and_wait_for send_payload, recv_payload
52
+ end
53
+
54
+ def start_download url
55
+ send_opcode= ML_S_download_url.class.opcode
56
+ sd= ML_message.new send_opcode, ML_S_download_url.new( :url=> url )
57
+ add_to_send_queue sd
58
+ end
59
+
60
+ protected
61
+
62
+
63
+
64
+ def send_and_wait_for send_payload, recv_payload
65
+ @data= nil
66
+ send_opcode=send_payload.class.opcode
67
+ recv_opcode=recv_payload.opcode
68
+ msg= ML_message.new send_opcode, send_payload
69
+ add_listener recv_opcode, self, :handle
70
+ add_to_send_queue msg
71
+ timer= Time.now
72
+ while ! @data && timer > Time.now - TIME_OUT # seconds ago
73
+ sleep 0.5
74
+ end
75
+ remove_listener recv_opcode, self, :handle
76
+ return @data.payload if @data
77
+ nil
78
+ end
79
+
80
+
81
+ def add_listener opcode, listener, method
82
+ # puts "Added: #{opcode}, #{listener}, #{method}"
83
+ @listener[opcode]= [] unless @listener[opcode]
84
+ @listener[opcode]<<[listener,method]
85
+ end
86
+
87
+ def remove_listener opcode, listener, method
88
+ # puts "removed: #{opcode}, #{listener}, #{method}"
89
+ @listener[opcode].delete [listener,method]
90
+ end
91
+
92
+ def add_to_send_queue msg
93
+ @send_queue<< msg
94
+ end
95
+
96
+ def handle msg
97
+ @data= msg
98
+ end
99
+
100
+ def log msg
101
+ # puts msg.inspect
102
+ end
103
+
104
+ private
105
+ def connect host, port, user, password
106
+ @socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
107
+ sockaddr = Socket.pack_sockaddr_in( port, host )
108
+ @socket.connect( sockaddr )
109
+ if get_core_protocol
110
+ send_protocol_version
111
+ send_interested_in_sources
112
+ first_message= login user, password
113
+ if first_message.opcode.payload== ML_R_bad_password.opcode
114
+ raise "Wrong credentials"
115
+ end
116
+ do_handle @listener, first_message
117
+ Thread.abort_on_exception = true
118
+ @thread= Thread.new(@socket,@send_queue,@listener) do |socket,send_queue,listener|
119
+ loop do
120
+ msg_to_send= send_queue.shift
121
+ send_message msg_to_send if msg_to_send
122
+ msg_received= receive_message
123
+ do_handle listener, msg_received if msg_received
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ def receive_message
130
+ selected= select( [@socket], nil, nil, 0.5 )
131
+ if selected
132
+ socket= selected[0][0]
133
+ paket_size= ML_int32.decode( socket.recvfrom( ML_int32.size )[0])
134
+ end
135
+ result= nil
136
+ if paket_size
137
+ opcode= ML_int16.decode( socket.recvfrom( ML_int16.size )[0])
138
+ raw_data= socket.recvfrom( paket_size.payload - opcode.size )
139
+ handler= ML_payload_handler.for( opcode.payload )
140
+ unless handler
141
+ result=ML_message.new opcode, ML_R_unknown.new( {:raw_data=> raw_data.inspect } )
142
+ else
143
+ payload= ML_payload_handler.for( opcode.payload ).decode( raw_data[0] )
144
+ result=ML_message.new opcode, payload
145
+ end
146
+ end
147
+ return result
148
+ end
149
+
150
+ def send_message msg
151
+ @socket.write msg.encode
152
+ end
153
+
154
+ def do_handle listener, msg
155
+ listener= listener[msg.opcode.payload]
156
+ listener.each do |l,method|
157
+ l.send method, msg
158
+ end if listener
159
+ end
160
+
161
+ # Handling of basic messages for starting connection
162
+
163
+ def get_core_protocol
164
+ cp= receive_message
165
+
166
+ return cp.opcode.payload==ML_R_core_protocol.opcode &&
167
+ cp.payload.max_protocol_version.payload>= PROTOCOL_VERSION &&
168
+ cp.payload.max_opcode_sent.payload>= MAX_OPCODE_SENT &&
169
+ cp.payload.max_opcode_rcvd.payload>= MAX_OPCODE_RCVD
170
+ end
171
+
172
+ def send_protocol_version
173
+ opcode= 0
174
+ pv= ML_message.new opcode, ML_S_protocol_version.new( :protocol_version=>PROTOCOL_VERSION )
175
+ send_message pv
176
+ end
177
+
178
+ def send_interested_in_sources
179
+ opcode= 64
180
+ pv= ML_message.new opcode, ML_S_interested_in_sources.new( :interested_in_sources=>0 )
181
+ send_message pv
182
+ end
183
+
184
+ def login user, password
185
+ opcode= 52
186
+ login_msg= ML_message.new opcode, ML_S_password.new( {:password=>password, :login_name=>user} )
187
+ send_message login_msg
188
+ receive_message
189
+ end
190
+
191
+ end
192
+ end
@@ -0,0 +1,339 @@
1
+ # ml_ruby: Ruby Bindings for the ML-Donkey GUI protocol
2
+ # Copyright (C) 2008 Jens Herrmann
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ module ML_ruby
19
+ class ML_atom
20
+ attr_reader :payload
21
+ def initialize payload
22
+ @payload= payload
23
+ end
24
+ def size
25
+ self.class.size
26
+ end
27
+ def self.size
28
+ @size
29
+ end
30
+ def self.packstring
31
+ @packstring
32
+ end
33
+ def encode
34
+ [ @payload ].pack self.class.packstring
35
+ end
36
+ def self.decode data
37
+ self.new( data.unpack( self.packstring )[0] )
38
+ end
39
+ def inspect
40
+ "#{self.class.name}: #{@payload}"
41
+ end
42
+ def == other
43
+ false if not other
44
+ @payload== other.payload
45
+ end
46
+ end
47
+
48
+ class ML_int64 < ML_atom; @size= 8; @packstring= 'Q'; end
49
+ class ML_int32 < ML_atom; @size= 4; @packstring= 'L'; end
50
+ class ML_uint32 < ML_atom; @size= 4; @packstring= 'L'; end
51
+ class ML_int16 < ML_atom; @size= 2; @packstring= 'S'; end
52
+ class ML_int8 < ML_atom; @size= 1; @packstring= 'C'; end
53
+ class ML_char < ML_atom; @size= 1; @packstring= 'a'; end
54
+ class ML_char16 < ML_atom; @size= 16; @packstring= 'a16'; end
55
+
56
+ class ML_list
57
+ attr_reader :payload
58
+ def initialize payload
59
+ @payload= payload
60
+ end
61
+ def size
62
+ ML_int16.size + @payload.inject( 0 ) {|sum,elem| sum+elem.size}
63
+ end
64
+ def encode
65
+ ML_int16.new( @payload.size ).encode + @payload.inject("") {|sum,elem| sum+elem.encode }
66
+ end
67
+ def self.decode data
68
+ # puts self.name, data.inspect
69
+ len= ML_int16.decode data
70
+ data= data[len.size..-1]
71
+ result=[]
72
+ len.payload.times do
73
+ elem= @type.decode( data )
74
+ # puts self.name, elem.to_yaml
75
+ result<< elem
76
+ data= data[elem.size..-1]
77
+ end
78
+ self.new result
79
+ end
80
+ def == other
81
+ false unless other
82
+ payload == other.payload
83
+ end
84
+ end
85
+
86
+ class ML_string < ML_list
87
+ @type= ML_char
88
+ def initialize payload
89
+ if payload.is_a?( Array )
90
+ super payload
91
+ else
92
+ @payload= payload.scan(/./).inject([]) {|sum,char| sum<< ML_char.new( char ) }
93
+ end
94
+ end
95
+ def payload
96
+ @payload.map {|c|c.payload}.join
97
+ end
98
+ def inspect
99
+ "#{self.class.name}: \"#{payload}\""
100
+ end
101
+ end
102
+
103
+ class ML_float < ML_string
104
+ @type= ML_char
105
+ def initialize payload
106
+ # puts payload.inspect
107
+ unless payload.is_a? Array
108
+ if (payload*100).to_i % 10 == 0
109
+ payload= payload.to_s + "0"
110
+ else
111
+ payload= payload.to_s.gsub(/\.0/,'.')
112
+ end
113
+ end
114
+ super payload
115
+ end
116
+ def payload
117
+ @payload.map {|c|c.payload}.join.gsub(/\.(\d)$/,'.0\1').to_f
118
+ end
119
+ end
120
+
121
+ class ML_list_of_int16 < ML_list
122
+ @type= ML_int16
123
+ end
124
+ class ML_list_of_int32 < ML_list
125
+ @type= ML_int32
126
+ end
127
+ class ML_list_of_string < ML_list
128
+ @type= ML_string
129
+ end
130
+
131
+ class ML_compound
132
+ def self.attributes
133
+ @attributes
134
+ end
135
+ def self.conditions
136
+ @conditions
137
+ end
138
+ def initialize data
139
+ self.class.attributes.each do |attr,type|
140
+ set_compound_attribute( attr, data[attr], type )
141
+ end
142
+ if self.class.conditions
143
+ self.class.conditions.each do |test,extra|
144
+ key=data[test].payload
145
+ extra[key].each do |attr,type|
146
+ set_compound_attribute( attr, data[attr], type )
147
+ end if extra[key]
148
+ end
149
+ end
150
+ end
151
+ def size
152
+ self.class.attributes.inject( 0 ) { |sum,attr| sum+send( attr[0] ).size }
153
+ end
154
+ def encode
155
+ result=""
156
+ self.class.attributes.each do |attr,type|
157
+ result<<( send( attr ).encode )
158
+ end
159
+ if self.class.conditions
160
+ # puts attributes.inspect
161
+ self.class.conditions.each do |test,extra|
162
+ # puts "testing #{[test,extra].inspect}"
163
+ key= send( test ).payload
164
+ extra[key].each do |attr,type|
165
+ result<<( send( attr ).encode )
166
+ end if extra[key]
167
+ end
168
+ end
169
+ result
170
+ end
171
+ def self.decode data
172
+ # puts data.inspect
173
+ attributes={}
174
+ self.attributes.each do |attr,type|
175
+ attributes[attr]= type.decode data
176
+ data= data[attributes[attr].size..-1]
177
+ end
178
+ if conditions
179
+ # puts attributes.inspect
180
+ conditions.each do |test,extra|
181
+ # puts "testing #{[test,extra].inspect}"
182
+ key= attributes[test].payload
183
+ extra[key].each do |attr,type|
184
+ attributes[attr]= type.decode data
185
+ data= data[attributes[attr].size..-1]
186
+ end if extra[key]
187
+ end
188
+ end
189
+ self.new attributes
190
+ end
191
+ protected
192
+ def self.attr_reader *sym
193
+ super *sym
194
+ end
195
+ def set_compound_attribute( attr, value, type )
196
+ # puts [attr, value, type].inspect
197
+ self.class.attr_reader attr
198
+ if value.is_a? type
199
+ eval "@#{attr}= value"
200
+ else
201
+ eval "@#{attr}= #{type}.new value"
202
+ end
203
+ end
204
+ end
205
+
206
+ class ML_filestate < ML_compound
207
+ @attributes= [
208
+ [:state,ML_int8],
209
+ ]
210
+ @conditions= [[:state,
211
+ { 6=>[
212
+ [:reason,ML_string],
213
+ ]
214
+ },
215
+ ]]
216
+ end
217
+
218
+ class ML_availability < ML_compound
219
+ @attributes= [
220
+ [:network,ML_int32],
221
+ [:chunks,ML_string],
222
+ ]
223
+ end
224
+ class ML_list_of_availability < ML_list
225
+ @type= ML_availability
226
+ end
227
+
228
+ class ML_ogg_stream_tags < ML_compound
229
+ @attributes=[
230
+ # TODO: http://mldonkey.sourceforge.net/GuiOGGStreamTag
231
+ ]
232
+ end
233
+ class ML_list_of_ogg_stream_tags < ML_list
234
+ @type= ML_ogg_stream_tags
235
+ end
236
+ class ML_ogg_stream < ML_compound
237
+ @attributes=[
238
+ [:number=>ML_int32],
239
+ [:type=>ML_int8],
240
+ [:tags=>ML_list_of_ogg_stream_tags]
241
+ ]
242
+ end
243
+
244
+ class ML_list_of_ogg_stream < ML_list
245
+ @type= ML_ogg_stream
246
+ end
247
+
248
+ class ML_subfile < ML_compound
249
+ @attributes=[
250
+ [:name=>ML_string],
251
+ [:size=>ML_int64],
252
+ [:format=>ML_string]
253
+ ]
254
+ end
255
+
256
+ class ML_list_of_subfile < ML_list
257
+ @type= ML_subfile
258
+ end
259
+
260
+ class ML_comment < ML_compound
261
+ @attributes=[
262
+ [:ip=>ML_int32],
263
+ [:geo_ip=>ML_int8],
264
+ [:name=>ML_string],
265
+ [:rating=>ML_int64],
266
+ [:comment=>ML_string]
267
+ ]
268
+ end
269
+
270
+ class ML_list_of_comment < ML_list
271
+ @type= ML_comment
272
+ end
273
+
274
+ class ML_fileformat < ML_compound
275
+ @attributes= [
276
+ [:format,ML_int8],
277
+ ]
278
+ @conditions= [[:format,
279
+ { 1=>[
280
+ [:extension,ML_string],
281
+ [:kind,ML_string],
282
+ ],
283
+ 2=>[
284
+ [:codec=>ML_string],
285
+ [:width=>ML_int32],
286
+ [:height=>ML_int32],
287
+ [:fps=>ML_int32],
288
+ [:rate=>ML_int32],
289
+ ],
290
+ 3=>[
291
+ [:mp3_title=>ML_string],
292
+ [:mp3_artist=>ML_string],
293
+ [:mp3_album=>ML_string],
294
+ [:mp3_year=>ML_string],
295
+ [:mp3_comment=>ML_string],
296
+ [:mp3_tracknum=>ML_int32],
297
+ [:mp3_genre=>ML_int32],
298
+ ],
299
+ 4=>[
300
+ [:stream=>ML_list_of_ogg_stream]
301
+ ]
302
+ },
303
+ ]]
304
+ end
305
+
306
+ class ML_fileinfo < ML_compound
307
+ @attributes= [
308
+ [:id, ML_int32],
309
+ [:network_id, ML_int32],
310
+ [:file_names, ML_list_of_string],
311
+ [:md4, ML_char16],
312
+ [:file_size,ML_int64],
313
+ [:downloaded,ML_int64],
314
+ [:sources,ML_int32],
315
+ [:clients,ML_int32],
316
+ [:state,ML_filestate],
317
+ [:chunks,ML_string],
318
+ [:availability,ML_list_of_availability],
319
+ [:speed,ML_float],
320
+ [:chunks_ages,ML_list_of_int32],
321
+ [:file_age,ML_int32],
322
+ [:file_format,ML_fileformat],
323
+ [:preferred_name,ML_string],
324
+ [:last_seen,ML_int32],
325
+ [:priority,ML_uint32],
326
+ [:comment,ML_string],
327
+ [:links,ML_list_of_string],
328
+ [:subfiles,ML_list_of_subfile],
329
+ [:file_format_im,ML_string],
330
+ [:comments,ML_list_of_comment],
331
+ [:file_user,ML_string],
332
+ [:file_group,ML_string],
333
+ ]
334
+ end
335
+
336
+ class ML_list_of_fileinfo < ML_list
337
+ @type= ML_fileinfo
338
+ end
339
+ end
@@ -0,0 +1,161 @@
1
+ # ml_ruby: Ruby Bindings for the ML-Donkey GUI protocol
2
+ # Copyright (C) 2008 Jens Herrmann
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require File.dirname(__FILE__) + '/ml_data_types'
19
+
20
+ module ML_ruby
21
+ class ML_payload < ML_compound
22
+ def self.opcode
23
+ @opcode
24
+ end
25
+ end
26
+
27
+ class ML_message
28
+ attr_reader :size, :opcode, :payload
29
+ def initialize opcode=nil, payload=nil
30
+ if opcode && opcode.is_a?( ML_int16 )
31
+ @opcode= opcode
32
+ elsif opcode
33
+ @opcode= ML_int16.new( opcode )
34
+ end
35
+ @payload= payload if payload
36
+ @size= ML_int32.new( @opcode.size + (payload ? payload.size : 0) ) if opcode
37
+ end
38
+ def encode
39
+ @size.encode + @opcode.encode + @payload.encode
40
+ end
41
+ end
42
+
43
+ class ML_S_protocol_version < ML_payload
44
+ @opcode= 0
45
+ @attributes= [
46
+ [:protocol_version,ML_int32]
47
+ ]
48
+ end
49
+
50
+ class ML_S_interested_in_sources < ML_payload
51
+ @opcode= 64
52
+ @attributes= [
53
+ [:interested_in_sources,ML_int8]
54
+ ]
55
+ end
56
+
57
+ class ML_S_password < ML_payload
58
+ @opcode= 52
59
+ @attributes= [
60
+ [:password,ML_string],
61
+ [:login_name,ML_string],
62
+ ]
63
+ end
64
+
65
+ class ML_S_get_downloading_files < ML_payload
66
+ @opcode= 45
67
+ @attributes= [
68
+ ]
69
+ end
70
+
71
+ class ML_S_get_downloaded_files < ML_payload
72
+ @opcode= 46
73
+ @attributes= [
74
+ ]
75
+ end
76
+
77
+ class ML_S_download_url< ML_payload
78
+ @opcode= 8
79
+ @attributes= [
80
+ [:url,ML_string],
81
+ ]
82
+ end
83
+
84
+ class ML_R_core_protocol < ML_payload
85
+ @opcode= 0
86
+ @attributes= [
87
+ [:max_protocol_version,ML_int32],
88
+ [:max_opcode_sent,ML_int32],
89
+ [:max_opcode_rcvd,ML_int32],
90
+ ]
91
+ end
92
+
93
+ class ML_R_network_info < ML_payload
94
+ @opcode= 20
95
+ @attributes= [
96
+ [:network_identifier,ML_int32],
97
+ [:network_name,ML_string],
98
+ [:enabled,ML_int8],
99
+ [:config_file,ML_string],
100
+ [:uploaded,ML_int64],
101
+ [:downloaded,ML_int64],
102
+ [:connected_servers,ML_int32],
103
+ [:network_flags,ML_list_of_int16],
104
+ ]
105
+ end
106
+
107
+ class ML_R_console_message < ML_payload
108
+ @opcode= 19
109
+ @attributes= [
110
+ [:message,ML_string],
111
+ ]
112
+ end
113
+
114
+ class ML_R_bad_password < ML_payload
115
+ @opcode= 47
116
+ @attributes= [
117
+ ]
118
+ end
119
+
120
+ class ML_R_fileinfo < ML_payload
121
+ @opcode= 52
122
+ @attributes= [
123
+ [:fileinfo,ML_fileinfo],
124
+ ]
125
+ end
126
+
127
+ class ML_R_downloading_files < ML_payload
128
+ @opcode= 53
129
+ @attributes= [
130
+ [:list,ML_list_of_fileinfo],
131
+ ]
132
+ end
133
+
134
+ class ML_R_downloaded_files < ML_payload
135
+ @opcode= 54
136
+ @attributes= [
137
+ [:list,ML_list_of_fileinfo],
138
+ ]
139
+ end
140
+
141
+ class ML_R_unknown < ML_payload
142
+ @attributes= [
143
+ [:raw_data,ML_string],
144
+ ]
145
+ end
146
+
147
+ class ML_payload_handler
148
+ Types={
149
+ 0 => ML_R_core_protocol,
150
+ 19 => ML_R_console_message,
151
+ 20 => ML_R_network_info,
152
+ 47 => ML_R_bad_password,
153
+ 52 => ML_R_fileinfo,
154
+ 53 => ML_R_downloading_files,
155
+ 54 => ML_R_downloaded_files,
156
+ }
157
+ def self.for opcode
158
+ Types[opcode]
159
+ end
160
+ end
161
+ end
data/rakefile.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+
6
+ task :default => :test
7
+
8
+ desc "Run the tests"
9
+ Rake::TestTask::new do |t|
10
+ t.test_files = FileList['test/test*.rb']
11
+ t.verbose = true
12
+ end
13
+
14
+ desc "Generate the documentation"
15
+ Rake::RDocTask::new do |rdoc|
16
+ rdoc.rdoc_dir = 'ml-ruby-doc/'
17
+ rdoc.title = "ML-Ruby Documentation"
18
+ rdoc.options << '--line-numbers' << '--inline-source'
19
+ rdoc.rdoc_files.include('README')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ spec = Gem::Specification::new do |s|
24
+ s.platform = Gem::Platform::RUBY
25
+
26
+ s.name = 'ml-ruby'
27
+ s.version = "0.0.1"
28
+ s.summary = "ML Ruby are the ruby bindings for the open source peer 2 peer software MLDonkey. This is the first part of an alternative to the official web GUI written in Ruby On Rails."
29
+ s.description = <<EOF
30
+ EOF
31
+ s.author = 'Jens Herrmann'
32
+ s.email = 'interesse@rubyforge.org'
33
+ s.homepage = "http://rubyforge.org/projects/ml-ruby/"
34
+
35
+ s.requirements << 'none'
36
+ s.require_path = 'lib'
37
+ s.files = FileList["lib/**/*.rb","test/**/*.rb", "README","rakefile.rb"]
38
+ s.test_files = FileList['test/test*.rb']
39
+
40
+ s.has_rdoc = true
41
+ s.extra_rdoc_files = ["README"]
42
+ s.rdoc_options.concat ['--main', 'README']
43
+ end
44
+
45
+ desc "Package the library as a gem"
46
+ Rake::GemPackageTask.new(spec) do |pkg|
47
+ pkg.need_zip = true
48
+ pkg.need_tar = true
49
+ end
@@ -0,0 +1,42 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'ml-ruby'
4
+ require 'test/unit'
5
+
6
+ include ML_ruby
7
+
8
+ class TestDatatypes <Test::Unit::TestCase
9
+
10
+ def test_atom_inspect
11
+ assert_equal "ML_ruby::ML_atom: 0", ML_atom.new(0).inspect
12
+ end
13
+
14
+ def test_int64
15
+ assert_equal 0, ML_int64.decode( ML_int64.new(0).encode ).payload
16
+ end
17
+
18
+ def test_simple
19
+ [ML_int64,ML_int32,ML_uint32,ML_int16,ML_int8,].each do |type|
20
+ assert_equal 0, type.decode( type.new(0).encode ).payload
21
+ end
22
+ assert_equal "T", ML_char.decode( ML_char.new("T").encode ).payload
23
+ assert_equal "0123456789abcdef", ML_char16.decode( ML_char16.new("0123456789abcdef").encode ).payload
24
+ end
25
+
26
+ def test_string
27
+ assert_equal "Test", ML_string.decode( ML_string.new("Test").encode ).payload
28
+ end
29
+
30
+ def test_float
31
+ assert_equal 0.0, ML_float.decode( ML_float.new(0.0).encode ).payload
32
+ assert_equal 0.1, ML_float.decode( ML_float.new(0.1).encode ).payload
33
+ assert_equal 0.01, ML_float.decode( ML_float.new(0.01).encode ).payload
34
+ end
35
+
36
+ def test_list_of
37
+ assert_equal [ML_int16.new(0),ML_int16.new(1)], ML_list_of_int16.decode( ML_list_of_int16.new([ML_int16.new(0),ML_int16.new(1)]).encode ).payload
38
+ assert_equal [ML_int32.new(0),ML_int32.new(1)], ML_list_of_int32.decode( ML_list_of_int32.new([ML_int32.new(0),ML_int32.new(1)]).encode ).payload
39
+ assert_equal [ML_string.new('null'),ML_string.new('eins')], ML_list_of_string.decode( ML_list_of_string.new([ML_string.new('null'),ML_string.new('eins')]).encode ).payload
40
+ end
41
+
42
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ml-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jens Herrmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-02-20 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ""
17
+ email: interesse@rubyforge.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - lib/ml-ruby/ml_client.rb
26
+ - lib/ml-ruby/ml_data_types.rb
27
+ - lib/ml-ruby/ml_protocol.rb
28
+ - lib/ml-ruby.rb
29
+ - test/test_datatypes.rb
30
+ - README
31
+ - rakefile.rb
32
+ has_rdoc: true
33
+ homepage: http://rubyforge.org/projects/ml-ruby/
34
+ post_install_message:
35
+ rdoc_options:
36
+ - --main
37
+ - README
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements:
53
+ - none
54
+ rubyforge_project:
55
+ rubygems_version: 1.0.1
56
+ signing_key:
57
+ specification_version: 2
58
+ summary: ML Ruby are the ruby bindings for the open source peer 2 peer software MLDonkey. This is the first part of an alternative to the official web GUI written in Ruby On Rails.
59
+ test_files:
60
+ - test/test_datatypes.rb