packet_io 0.4.0.rc2

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ == 0.4.0 / 2011-05-31
2
+ * much simpler reimplementation without threads
3
+
4
+ == 0.3.0 / 2008-10-12
5
+ * initial release
6
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Levin Alexander
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,42 @@
1
+ serial_interface
2
+ by Levin Alexander
3
+ http://levinalex.net/
4
+
5
+ == DESCRIPTION:
6
+
7
+ serial_interface intends to be a small library that makes it easy
8
+ to define packet based protocols over a serial link (RS232) in a
9
+ declarative fashion.
10
+
11
+ == SYNOPSIS:
12
+
13
+ nothing written yet
14
+
15
+ == INSTALL:
16
+
17
+ * not yet written
18
+
19
+ == LICENSE:
20
+
21
+ (The MIT License)
22
+
23
+ Copyright (c) 2006-2008 Levin Alexander
24
+
25
+ Permission is hereby granted, free of charge, to any person obtaining
26
+ a copy of this software and associated documentation files (the
27
+ 'Software'), to deal in the Software without restriction, including
28
+ without limitation the rights to use, copy, modify, merge, publish,
29
+ distribute, sublicense, and/or sell copies of the Software, and to
30
+ permit persons to whom the Software is furnished to do so, subject to
31
+ the following conditions:
32
+
33
+ The above copyright notice and this permission notice shall be
34
+ included in all copies or substantial portions of the Software.
35
+
36
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
37
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
38
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
39
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
40
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
41
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
42
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift './lib'
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'packet_io'
7
+
8
+ require 'rake/testtask'
9
+ Rake::TestTask.new(:test) do |test|
10
+ test.libs << 'lib' << 'test'
11
+ test.pattern = 'test/**/test_*.rb'
12
+ test.verbose = true
13
+ end
14
+
15
+ require 'yard'
16
+ YARD::Rake::YardocTask.new
17
+
18
+ task :doc => :yard
19
+ task :default => [:test]
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1,113 @@
1
+ module PacketIO
2
+
3
+ # a chainable IO-Listener that provides two methods:
4
+ #
5
+ # {#on_data} ::
6
+ # a callback that is called whenever a message is received
7
+ # {#write} ::
8
+ # can be called so send messages to the underlying IO
9
+ #
10
+ # when overriding this class, you need to implement two methods:
11
+ #
12
+ # {#receive} ::
13
+ # is called from an underlying IO whenever a message is received
14
+ # the message can be handled. Call {#forward} to propagate
15
+ #
16
+ # {#write} ::
17
+ # transform/encode a message before sending it. Call +super+ to propagate
18
+ #
19
+ # See {LineBasedProtocol} for a toy implementation which strips
20
+ # newlines and only forwards complete lines.
21
+ #
22
+ class Base
23
+
24
+ # @param [Base, #on_data] read data source
25
+ # @param [Base, IO, #write] write object where messages are written to
26
+ #
27
+ def initialize(read, write = read)
28
+ @reader, @writer = read, write
29
+ @on_data = nil
30
+ @reader.on_data { |*data| receive(*data) } if @reader.respond_to?(:on_data)
31
+ end
32
+
33
+ # register a block, to be run whenever the protocol implementation
34
+ # receives data (by calling {#forward})
35
+ #
36
+ # this is used to chain protocol layers together
37
+ #
38
+ # @return [self]
39
+ # @yield [*args] called whenever the protocol implementaion calls {#forward}
40
+ # @yieldreturn [nil]
41
+ #
42
+ def on_data(&block)
43
+ @on_data = block
44
+ self
45
+ end
46
+
47
+ # @see #write
48
+ #
49
+ def <<(*args)
50
+ write(*args)
51
+ end
52
+
53
+ # write data to underlying interface. override if data needs to be preprocessed
54
+ #
55
+ def write(*args)
56
+ @writer.<<(*args) if @writer
57
+ end
58
+
59
+
60
+ protected
61
+
62
+ # override this method to handle data received from an underlying interface, for
63
+ # example splitting it into messages or only passing on complete lines
64
+ # (see {LineBasedProtocol#receive} for an example)
65
+ #
66
+ # call {#forward} to pass it on to higher levels
67
+ #
68
+ # @return [nil]
69
+ #
70
+ def receive(data)
71
+ forward(data)
72
+ end
73
+
74
+ def forward(*data)
75
+ @on_data.call(*data) if @on_data
76
+ end
77
+ end
78
+
79
+
80
+ class LineBasedProtocol < Base
81
+
82
+ # strip newlines from received data and pass on complete lines
83
+ #
84
+ # @param [String] data
85
+ #
86
+ def receive(data)
87
+ @memo ||= ""
88
+ scanner = StringScanner.new(@memo + data)
89
+ while s = scanner.scan(/.*?\n/)
90
+ forward(s.strip)
91
+ end
92
+ @memo = scanner.rest
93
+ nil
94
+ end
95
+
96
+ # add a newline to data and pass it on
97
+ # @param [String] data
98
+ #
99
+ def write(data)
100
+ super(data + "\n")
101
+ end
102
+ end
103
+
104
+ class IOListener < Base
105
+ def run!
106
+ while not @reader.eof?
107
+ str = @reader.readpartial(4096)
108
+ forward(str)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
@@ -0,0 +1,49 @@
1
+ module PacketIO::Test
2
+ class MockServer
3
+ def initialize(read, write)
4
+ @read, @write = read, write
5
+ @queue = Queue.new
6
+ @thread = Thread.new do
7
+ parse_commands
8
+ end
9
+ end
10
+
11
+ def write(string)
12
+ @queue.push [:write, string]
13
+ self
14
+ end
15
+
16
+ def read_all
17
+ @read.readpartial(4096)
18
+ end
19
+
20
+ def wait(seconds = 0.02)
21
+ @queue.push [:wait, seconds]
22
+ self
23
+ end
24
+
25
+ def eof
26
+ @queue.push [:close]
27
+ end
28
+
29
+
30
+ private
31
+
32
+ def parse_commands
33
+ loop do
34
+ action, data = @queue.pop
35
+
36
+ case action
37
+ when :close
38
+ @write.close
39
+ break
40
+ when :write
41
+ @write.write(data)
42
+ @write.flush
43
+ when :wait
44
+ sleep data
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
data/lib/packet_io.rb ADDED
@@ -0,0 +1,8 @@
1
+
2
+ module PacketIO
3
+ VERSION = '0.4.0.rc2'
4
+ end
5
+
6
+ require 'strscan'
7
+ require 'packet_io/io_listener'
8
+
data/packet_io.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'packet_io'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{packet_io}
7
+ s.version = PacketIO::VERSION
8
+
9
+ s.authors = ["Levin Alexander"]
10
+ s.description = %q{}
11
+ s.email = %q{mail@levinalex.net}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+
17
+ s.homepage = %q{http://github.com/levinalex/packet_io}
18
+ s.rdoc_options = ["--charset=UTF-8"]
19
+ s.require_paths = ["lib"]
20
+ s.summary = %q{define packet based protocols in a declarative fashion}
21
+
22
+ s.add_development_dependency("shoulda", ["~> 2.11.3"])
23
+ s.add_development_dependency("mocha", ["~> 0.9.12"])
24
+ s.add_development_dependency("yard", ["~> 0.7.1"])
25
+ s.add_development_dependency("cucumber", ["~> 0.10.3"])
26
+ end
27
+
data/test/helper.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'packet_io'
9
+ require 'packet_io/test/mock_server'
10
+
11
+ class Test::Unit::TestCase
12
+ end
13
+
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+
3
+ class TestIOListener < Test::Unit::TestCase
4
+ context "a server" do
5
+ setup do
6
+ r1, w1 = IO.pipe # Server -> Client
7
+ r2, w2 = IO.pipe # Client -> Server
8
+
9
+ @server = PacketIO::IOListener.new(r1, w2)
10
+ @protocol = PacketIO::LineBasedProtocol.new(@server)
11
+ @device = PacketIO::Test::MockServer.new(r2, w1)
12
+ end
13
+
14
+ should "exist" do
15
+ assert_not_nil @server
16
+ end
17
+
18
+ should "yield packets written to it" do
19
+ @packets = []
20
+ @protocol.on_data { |packet| @packets << packet }
21
+
22
+ @device.write("fo").wait.write("o\n").wait.write("bar\n").eof
23
+ @server.run!
24
+
25
+ assert_equal ["foo", "bar"], @packets
26
+ end
27
+
28
+ should "send data" do
29
+ @protocol << "hello world"
30
+ data = @device.read_all
31
+ assert_equal "hello world\n", data
32
+ end
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: packet_io
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 0
7
+ - 4
8
+ - 0
9
+ - rc2
10
+ version: 0.4.0.rc2
11
+ platform: ruby
12
+ authors:
13
+ - Levin Alexander
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-31 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 2
31
+ - 11
32
+ - 3
33
+ version: 2.11.3
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: mocha
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ - 9
47
+ - 12
48
+ version: 0.9.12
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: yard
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ - 7
62
+ - 1
63
+ version: 0.7.1
64
+ type: :development
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: cucumber
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
76
+ - 10
77
+ - 3
78
+ version: 0.10.3
79
+ type: :development
80
+ version_requirements: *id004
81
+ description: ""
82
+ email: mail@levinalex.net
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files: []
88
+
89
+ files:
90
+ - .document
91
+ - .gitignore
92
+ - History.txt
93
+ - LICENSE
94
+ - README.rdoc
95
+ - Rakefile
96
+ - VERSION
97
+ - lib/packet_io.rb
98
+ - lib/packet_io/io_listener.rb
99
+ - lib/packet_io/test/mock_server.rb
100
+ - packet_io.gemspec
101
+ - test/helper.rb
102
+ - test/test_io_listener.rb
103
+ has_rdoc: true
104
+ homepage: http://github.com/levinalex/packet_io
105
+ licenses: []
106
+
107
+ post_install_message:
108
+ rdoc_options:
109
+ - --charset=UTF-8
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">"
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 1
127
+ - 3
128
+ - 1
129
+ version: 1.3.1
130
+ requirements: []
131
+
132
+ rubyforge_project:
133
+ rubygems_version: 1.3.7
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: define packet based protocols in a declarative fashion
137
+ test_files:
138
+ - test/helper.rb
139
+ - test/test_io_listener.rb