arpie 0.0.6 → 0.1.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/.gitignore +4 -0
 - data/.yardopts +1 -0
 - data/{BINARY_SPEC → BINARY.rdoc} +73 -28
 - data/Gemfile +8 -0
 - data/LICENCE +15 -0
 - data/PROTOCOLS.rdoc +46 -0
 - data/README.rdoc +17 -0
 - data/Rakefile +6 -114
 - data/arpie.gemspec +26 -0
 - data/examples/em.rb +18 -0
 - data/lib/arpie.rb +2 -4
 - data/lib/arpie/binary.rb +18 -4
 - data/lib/arpie/binary/bytes_type.rb +7 -2
 - data/lib/arpie/binary/fixed_type.rb +11 -4
 - data/lib/arpie/binary/list_type.rb +2 -0
 - data/lib/arpie/binary/pack_type.rb +20 -10
 - data/lib/arpie/em.rb +48 -0
 - data/lib/arpie/error.rb +2 -4
 - data/lib/arpie/protocol.rb +7 -23
 - data/lib/arpie/version.rb +3 -0
 - data/spec/binary_spec.rb +113 -8
 - data/spec/bytes_binary_type_spec.rb +16 -3
 - data/spec/em_spec.rb +27 -0
 - data/spec/examples_spec.rb +11 -0
 - data/spec/fixed_binary_type_spec.rb +2 -2
 - data/spec/list_binary_type_spec.rb +9 -0
 - data/spec/protocol_merge_and_split_spec.rb +3 -3
 - data/spec/protocol_spec.rb +20 -43
 - data/spec/spec_helper.rb +13 -12
 - metadata +74 -83
 - data/COPYING +0 -15
 - data/README +0 -167
 - data/lib/arpie/client.rb +0 -195
 - data/lib/arpie/proxy.rb +0 -143
 - data/lib/arpie/server.rb +0 -157
 - data/lib/arpie/xmlrpc.rb +0 -108
 - data/spec/client_server_spec.rb +0 -107
 - data/tools/benchmark.rb +0 -52
 - data/tools/protocol_benchmark.rb +0 -42
 
    
        data/examples/em.rb
    ADDED
    
    | 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'arpie'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'eventmachine'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            EM::run {
         
     | 
| 
      
 6 
     | 
    
         
            +
              EM::start_server "127.0.0.1", 51210, Arpie::EventMachine::ArpieProtocol,
         
     | 
| 
      
 7 
     | 
    
         
            +
                Arpie::SeparatorProtocol.new do |c|
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def c.receive message
         
     | 
| 
      
 9 
     | 
    
         
            +
                    puts message.reverse
         
     | 
| 
      
 10 
     | 
    
         
            +
                    EM::stop_event_loop
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              EM::connect "127.0.0.1", 51210, Arpie::EventMachine::ArpieProtocol,
         
     | 
| 
      
 15 
     | 
    
         
            +
                Arpie::SeparatorProtocol.new do |c|
         
     | 
| 
      
 16 
     | 
    
         
            +
                  c.send "hi"
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
            }
         
     | 
    
        data/lib/arpie.rb
    CHANGED
    
    
    
        data/lib/arpie/binary.rb
    CHANGED
    
    | 
         @@ -50,7 +50,7 @@ module Arpie 
     | 
|
| 
       50 
50 
     | 
    
         
             
                @@description ||= {}
         
     | 
| 
       51 
51 
     | 
    
         
             
                @@hooks       ||= {}
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                 
     | 
| 
      
 53 
     | 
    
         
            +
                # @private
         
     | 
| 
       54 
54 
     | 
    
         
             
                @@anonymous ||= {}
         
     | 
| 
       55 
55 
     | 
    
         
             
                def self.__anonymous
         
     | 
| 
       56 
56 
     | 
    
         
             
                  @@anonymous[self]
         
     | 
| 
         @@ -58,7 +58,6 @@ module Arpie 
     | 
|
| 
       58 
58 
     | 
    
         
             
                def self.__anonymous= x
         
     | 
| 
       59 
59 
     | 
    
         
             
                  @@anonymous[self] = x
         
     | 
| 
       60 
60 
     | 
    
         
             
                end
         
     | 
| 
       61 
     | 
    
         
            -
                #:startdoc:
         
     | 
| 
       62 
61 
     | 
    
         | 
| 
       63 
62 
     | 
    
         
             
                def initialize
         
     | 
| 
       64 
63 
     | 
    
         
             
                  @fields = {}
         
     | 
| 
         @@ -229,6 +228,17 @@ module Arpie 
     | 
|
| 
       229 
228 
     | 
    
         
             
                  end
         
     | 
| 
       230 
229 
     | 
    
         
             
                end
         
     | 
| 
       231 
230 
     | 
    
         | 
| 
      
 231 
     | 
    
         
            +
                # You can use the field type as a class method to create new fields,
         
     | 
| 
      
 232 
     | 
    
         
            +
                # as if you would call Binary.field with the appropriate parameters.
         
     | 
| 
      
 233 
     | 
    
         
            +
                #
         
     | 
| 
      
 234 
     | 
    
         
            +
                # Examples:
         
     | 
| 
      
 235 
     | 
    
         
            +
                #   uint8 :nameof, :default => 1
         
     | 
| 
      
 236 
     | 
    
         
            +
                #   fixed :fixedValue, :value => [1,2,3].pack("CCC")
         
     | 
| 
      
 237 
     | 
    
         
            +
                #   list :ls, :of => :uint8, :sizeof => :nameof
         
     | 
| 
      
 238 
     | 
    
         
            +
                def self.method_missing meth, *va, &block
         
     | 
| 
      
 239 
     | 
    
         
            +
                  self.field(va.shift, meth, *va, &block)
         
     | 
| 
      
 240 
     | 
    
         
            +
                end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
       232 
242 
     | 
    
         
             
                # Specify that this Binary has a field of type +type+.
         
     | 
| 
       233 
243 
     | 
    
         
             
                # See the class documentation for usage.
         
     | 
| 
       234 
244 
     | 
    
         
             
                def self.field name, type = nil, opts = {}, &block
         
     | 
| 
         @@ -331,7 +341,7 @@ module Arpie 
     | 
|
| 
       331 
341 
     | 
    
         
             
                # a complete Binary.
         
     | 
| 
       332 
342 
     | 
    
         
             
                def self.from binary, opts = {}
         
     | 
| 
       333 
343 
     | 
    
         
             
                  @@fields[self] ||= []
         
     | 
| 
       334 
     | 
    
         
            -
                  binary = * self.call_hooks(:pre_from, binary)
         
     | 
| 
      
 344 
     | 
    
         
            +
                  binary, * = * self.call_hooks(:pre_from, binary)
         
     | 
| 
       335 
345 
     | 
    
         | 
| 
       336 
346 
     | 
    
         
             
                  consumed_bytes = 0
         
     | 
| 
       337 
347 
     | 
    
         
             
                  obj = new
         
     | 
| 
         @@ -373,7 +383,7 @@ module Arpie 
     | 
|
| 
       373 
383 
     | 
    
         
             
                  object.nil? and raise ArgumentError, "cannot #to nil"
         
     | 
| 
       374 
384 
     | 
    
         
             
                  @@fields[self] ||= []
         
     | 
| 
       375 
385 
     | 
    
         
             
                  r = []
         
     | 
| 
       376 
     | 
    
         
            -
                  object = * self.call_hooks(:pre_to, object)
         
     | 
| 
      
 386 
     | 
    
         
            +
                  object, * = * self.call_hooks(:pre_to, object)
         
     | 
| 
       377 
387 
     | 
    
         | 
| 
       378 
388 
     | 
    
         
             
                  @@fields[self].each {|field| # name, klass, kopts, inline_handler|
         
     | 
| 
       379 
389 
     | 
    
         
             
                    field.opts[:object] = object
         
     | 
| 
         @@ -435,5 +445,9 @@ module Arpie 
     | 
|
| 
       435 
445 
     | 
    
         
             
                def self.post_from &handler
         
     | 
| 
       436 
446 
     | 
    
         
             
                  self.add_hook(:post_from, handler)
         
     | 
| 
       437 
447 
     | 
    
         
             
                end
         
     | 
| 
      
 448 
     | 
    
         
            +
             
     | 
| 
      
 449 
     | 
    
         
            +
                private
         
     | 
| 
      
 450 
     | 
    
         
            +
                def self.to_ary *a
         
     | 
| 
      
 451 
     | 
    
         
            +
                end
         
     | 
| 
       438 
452 
     | 
    
         
             
              end
         
     | 
| 
       439 
453 
     | 
    
         
             
            end
         
     | 
| 
         @@ -29,7 +29,12 @@ module Arpie 
     | 
|
| 
       29 
29 
     | 
    
         
             
                  elsif opts[:length]
         
     | 
| 
       30 
30 
     | 
    
         
             
                    len = case opts[:length]
         
     | 
| 
       31 
31 
     | 
    
         
             
                      when :all
         
     | 
| 
       32 
     | 
    
         
            -
                         
     | 
| 
      
 32 
     | 
    
         
            +
                        if @pack_string == "Z"
         
     | 
| 
      
 33 
     | 
    
         
            +
                          npos = binary.index("\000") or raise EIncomplete
         
     | 
| 
      
 34 
     | 
    
         
            +
                          npos + 1
         
     | 
| 
      
 35 
     | 
    
         
            +
                        else
         
     | 
| 
      
 36 
     | 
    
         
            +
                          binary.size
         
     | 
| 
      
 37 
     | 
    
         
            +
                        end
         
     | 
| 
       33 
38 
     | 
    
         
             
                      when Symbol
         
     | 
| 
       34 
39 
     | 
    
         
             
                        opts[:object].send(opts[:length])
         
     | 
| 
       35 
40 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -74,7 +79,7 @@ module Arpie 
     | 
|
| 
       74 
79 
     | 
    
         
             
              Binary.register_type(BytesBinaryType.new("a", :length => 1), :char)
         
     | 
| 
       75 
80 
     | 
    
         
             
              Binary.register_type(BytesBinaryType.new("a"), :bytes)
         
     | 
| 
       76 
81 
     | 
    
         
             
              Binary.register_type(BytesBinaryType.new("A"), :string)
         
     | 
| 
       77 
     | 
    
         
            -
              Binary.register_type(BytesBinaryType.new("Z"), :nstring)
         
     | 
| 
      
 82 
     | 
    
         
            +
              Binary.register_type(BytesBinaryType.new("Z", :length => :all), :nstring)
         
     | 
| 
       78 
83 
     | 
    
         | 
| 
       79 
84 
     | 
    
         
             
              Binary.register_type(BytesBinaryType.new("M"), :quoted_printable)
         
     | 
| 
       80 
85 
     | 
    
         
             
              Binary.register_type(BytesBinaryType.new("m"), :base64)
         
     | 
| 
         @@ -7,6 +7,7 @@ module Arpie 
     | 
|
| 
       7 
7 
     | 
    
         
             
                def from binary, opts
         
     | 
| 
       8 
8 
     | 
    
         
             
                  opts[:value] or raise ArgumentError, "Requires option :value"
         
     | 
| 
       9 
9 
     | 
    
         
             
                  sz = opts[:value].size
         
     | 
| 
      
 10 
     | 
    
         
            +
                  binary.size >= sz or incomplete!
         
     | 
| 
       10 
11 
     | 
    
         
             
                  existing = binary.unpack("a#{sz}")[0]
         
     | 
| 
       11 
12 
     | 
    
         
             
                  existing == opts[:value] or bogon! nil, ":fixed did not match data in packet"
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
         @@ -23,13 +24,19 @@ module Arpie 
     | 
|
| 
       23 
24 
     | 
    
         
             
              class Binary
         
     | 
| 
       24 
25 
     | 
    
         
             
                # Create a static field.
         
     | 
| 
       25 
26 
     | 
    
         
             
                # This is an alias for:
         
     | 
| 
       26 
     | 
    
         
            -
                #  field :name, :fixed, :value => content
         
     | 
| 
      
 27 
     | 
    
         
            +
                #  field :name, :fixed, :value => content, :default => content
         
     | 
| 
       27 
28 
     | 
    
         
             
                #
         
     | 
| 
       28 
29 
     | 
    
         
             
                # If no name is specified, it is assumed that the user will
         
     | 
| 
       29 
30 
     | 
    
         
             
                # never want to access it and a suitable one is autogenerated.
         
     | 
| 
       30 
     | 
    
         
            -
                def self.static  
     | 
| 
       31 
     | 
    
         
            -
                   
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 31 
     | 
    
         
            +
                def self.static name_or_content, content = nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                  if content.nil?
         
     | 
| 
      
 33 
     | 
    
         
            +
                    name = "static-%x" % [name_or_content.hash]
         
     | 
| 
      
 34 
     | 
    
         
            +
                    content = name_or_content
         
     | 
| 
      
 35 
     | 
    
         
            +
                  else
         
     | 
| 
      
 36 
     | 
    
         
            +
                    name = name_or_content
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  field name, :fixed, :value => content, :default => content
         
     | 
| 
       33 
40 
     | 
    
         
             
                end
         
     | 
| 
       34 
41 
     | 
    
         | 
| 
       35 
42 
     | 
    
         
             
                # An alias for +static+.
         
     | 
| 
         @@ -14,16 +14,26 @@ module Arpie 
     | 
|
| 
       14 
14 
     | 
    
         
             
                    count = 1 if count == 0
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
                    length += case directive
         
     | 
| 
       17 
     | 
    
         
            -
                    when 'A', 'a', 'C', 'c', 'Z', 'x' 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                    when ' 
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    when ' 
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                    when ' 
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                    when ' 
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
                    when 'A', 'a', 'C', 'c', 'Z', 'x'
         
     | 
| 
      
 18 
     | 
    
         
            +
                      count
         
     | 
| 
      
 19 
     | 
    
         
            +
                    when 'B', 'b'
         
     | 
| 
      
 20 
     | 
    
         
            +
                      (count / 8.0).ceil
         
     | 
| 
      
 21 
     | 
    
         
            +
                    when 'D', 'd', 'E', 'G'
         
     | 
| 
      
 22 
     | 
    
         
            +
                      count * 8
         
     | 
| 
      
 23 
     | 
    
         
            +
                    when 'e', 'F', 'f', 'g'
         
     | 
| 
      
 24 
     | 
    
         
            +
                      count * 4
         
     | 
| 
      
 25 
     | 
    
         
            +
                    when 'H', 'h'
         
     | 
| 
      
 26 
     | 
    
         
            +
                      (count / 2.0).ceil
         
     | 
| 
      
 27 
     | 
    
         
            +
                    when 'I', 'i', 'L', 'l', 'N', 'V'
         
     | 
| 
      
 28 
     | 
    
         
            +
                      count * 4
         
     | 
| 
      
 29 
     | 
    
         
            +
                    when 'n', 'S', 's', 'v'
         
     | 
| 
      
 30 
     | 
    
         
            +
                      count * 2
         
     | 
| 
      
 31 
     | 
    
         
            +
                    when 'Q', 'q'
         
     | 
| 
      
 32 
     | 
    
         
            +
                      count * 8
         
     | 
| 
      
 33 
     | 
    
         
            +
                    when 'X'
         
     | 
| 
      
 34 
     | 
    
         
            +
                      count * -1
         
     | 
| 
      
 35 
     | 
    
         
            +
                    else
         
     | 
| 
      
 36 
     | 
    
         
            +
                      raise ArgumentError, "#{directive} is not supported"
         
     | 
| 
       27 
37 
     | 
    
         
             
                    end
         
     | 
| 
       28 
38 
     | 
    
         
             
                  end
         
     | 
| 
       29 
39 
     | 
    
         | 
    
        data/lib/arpie/em.rb
    ADDED
    
    | 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Arpie
         
     | 
| 
      
 2 
     | 
    
         
            +
              module EventMachine
         
     | 
| 
      
 3 
     | 
    
         
            +
                # A EventMachine protocol implementing a simple protocol
         
     | 
| 
      
 4 
     | 
    
         
            +
                # chain handler. To use, simply include it in your EM
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Connection moduleas you would any other EM protocol.
         
     | 
| 
      
 6 
     | 
    
         
            +
                #
         
     | 
| 
      
 7 
     | 
    
         
            +
                # The module expects a list of protocols given along with
         
     | 
| 
      
 8 
     | 
    
         
            +
                # the module initializer:
         
     | 
| 
      
 9 
     | 
    
         
            +
                #   EM::start_server host, port, ArpieProtocol,
         
     | 
| 
      
 10 
     | 
    
         
            +
                #     Arpie::MarshalProtocol.new, Arpie::SizedProtocol.new
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                # To receive messages, override <tt>receive(message)</tt>, which will
         
     | 
| 
      
 13 
     | 
    
         
            +
                # be called once for each message decoded with the given
         
     | 
| 
      
 14 
     | 
    
         
            +
                # protocols.
         
     | 
| 
      
 15 
     | 
    
         
            +
                #
         
     | 
| 
      
 16 
     | 
    
         
            +
                # To send messages back over the same connection, simply call
         
     | 
| 
      
 17 
     | 
    
         
            +
                # <tt>send(message)</tt>.
         
     | 
| 
      
 18 
     | 
    
         
            +
                module ArpieProtocol
         
     | 
| 
      
 19 
     | 
    
         
            +
                  attr_reader :chain
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def initialize *protocols
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @chain = Arpie::ProtocolChain.new(*protocols)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  # Receive a message. Override this in your implemention.
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def receive message
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def receive_data data
         
     | 
| 
      
 30 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 31 
     | 
    
         
            +
                      for msg in @chain.from(data)
         
     | 
| 
      
 32 
     | 
    
         
            +
                        receive msg
         
     | 
| 
      
 33 
     | 
    
         
            +
                      end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    rescue Arpie::EIncomplete
         
     | 
| 
      
 35 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  # Send a message, encoding it with the given
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # protocols.
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def send message
         
     | 
| 
      
 42 
     | 
    
         
            +
                    for msg in @chain.to(message)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      send_data(msg)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end # module EventMachine
         
     | 
| 
      
 48 
     | 
    
         
            +
            end # module Arpie
         
     | 
    
        data/lib/arpie/error.rb
    CHANGED
    
    | 
         @@ -6,18 +6,16 @@ module Arpie 
     | 
|
| 
       6 
6 
     | 
    
         
             
              class StreamError < IOError ; end
         
     | 
| 
       7 
7 
     | 
    
         
             
              # Raised by arpie when a Protocol needs more data to parse a packet.
         
     | 
| 
       8 
8 
     | 
    
         
             
              # Usually only of relevance to the programmer when using Protocol#from directly.
         
     | 
| 
       9 
     | 
    
         
            -
              class EIncomplete <  
     | 
| 
      
 9 
     | 
    
         
            +
              class EIncomplete < Errno::EAGAIN ; end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
              #  
     | 
| 
      
 11 
     | 
    
         
            +
              # @private
         
     | 
| 
       12 
12 
     | 
    
         
             
              # Used internally by arpie.
         
     | 
| 
       13 
     | 
    
         
            -
              class ETryAgain < RuntimeError ; end
         
     | 
| 
       14 
13 
     | 
    
         
             
              class YieldResult < RuntimeError
         
     | 
| 
       15 
14 
     | 
    
         
             
                attr_reader :result
         
     | 
| 
       16 
15 
     | 
    
         
             
                def initialize result
         
     | 
| 
       17 
16 
     | 
    
         
             
                  @result = result
         
     | 
| 
       18 
17 
     | 
    
         
             
                end
         
     | 
| 
       19 
18 
     | 
    
         
             
              end
         
     | 
| 
       20 
     | 
    
         
            -
              # :startdoc:
         
     | 
| 
       21 
19 
     | 
    
         | 
| 
       22 
20 
     | 
    
         
             
              # Call this if you think the stream has been corrupted, or
         
     | 
| 
       23 
21 
     | 
    
         
             
              # non-protocol data arrived.
         
     | 
    
        data/lib/arpie/protocol.rb
    CHANGED
    
    | 
         @@ -1,11 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'shellwords'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'psych' if RUBY_VERSION =~ /^1.9/
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'yaml'
         
     | 
| 
       3 
4 
     | 
    
         
             
            require 'zlib'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            module Arpie
         
     | 
| 
       6 
7 
     | 
    
         
             
              MTU = 1024
         
     | 
| 
       7 
     | 
    
         
            -
              # A RPC call. You need to wrap all calls sent over RPC protocols in this.
         
     | 
| 
       8 
     | 
    
         
            -
              class RPCall < Struct.new(:ns, :meth, :argv, :uuid); end
         
     | 
| 
       9 
8 
     | 
    
         | 
| 
       10 
9 
     | 
    
         
             
              # A ProtocolChain wraps one or more Protocols to provide a parser
         
     | 
| 
       11 
10 
     | 
    
         
             
              # list, into which io data can be fed and parsed packets received; and
         
     | 
| 
         @@ -22,10 +21,6 @@ module Arpie 
     | 
|
| 
       22 
21 
     | 
    
         
             
                # A buffer holding all parsed, but unreturned messages.
         
     | 
| 
       23 
22 
     | 
    
         
             
                attr_reader :messages
         
     | 
| 
       24 
23 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                # The endpoint class of this Protocol.
         
     | 
| 
       26 
     | 
    
         
            -
                # Defaults to Arpie::Endpoint
         
     | 
| 
       27 
     | 
    
         
            -
                attr_accessor :endpoint_class
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
24 
     | 
    
         
             
                # Create a new Chain. Supply an Array of Protocol
         
     | 
| 
       30 
25 
     | 
    
         
             
                # instances, where the leftmost is the innermost.
         
     | 
| 
       31 
26 
     | 
    
         
             
                #
         
     | 
| 
         @@ -39,8 +34,6 @@ module Arpie 
     | 
|
| 
       39 
34 
     | 
    
         
             
                      "The outermost protocol needs to be able to " +
         
     | 
| 
       40 
35 
     | 
    
         
             
                      "separate messages in a stream (#{protocols.inspect} does not)."
         
     | 
| 
       41 
36 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                  @endpoint_class = Arpie::Endpoint
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
37 
     | 
    
         
             
                  @chain = protocols
         
     | 
| 
       45 
38 
     | 
    
         
             
                  @buffer = ""
         
     | 
| 
       46 
39 
     | 
    
         
             
                  @messages = []
         
     | 
| 
         @@ -163,7 +156,7 @@ module Arpie 
     | 
|
| 
       163 
156 
     | 
    
         
             
                # Write +message+ to +io+.
         
     | 
| 
       164 
157 
     | 
    
         
             
                def write_message io, *messages
         
     | 
| 
       165 
158 
     | 
    
         
             
                  binary = messages.map {|m| to(m)}
         
     | 
| 
       166 
     | 
    
         
            -
                  io.write(binary)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  io.write(binary.flatten.join(""))
         
     | 
| 
       167 
160 
     | 
    
         
             
                end
         
     | 
| 
       168 
161 
     | 
    
         | 
| 
       169 
162 
     | 
    
         
             
                def reset
         
     | 
| 
         @@ -180,12 +173,12 @@ module Arpie 
     | 
|
| 
       180 
173 
     | 
    
         
             
                # message separation within a stream.
         
     | 
| 
       181 
174 
     | 
    
         
             
                CAN_SEPARATE_MESSAGES = false
         
     | 
| 
       182 
175 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
                #  
     | 
| 
      
 176 
     | 
    
         
            +
                # @private
         
     | 
| 
       184 
177 
     | 
    
         
             
                # The stowbuffer hash used by assemble! No need to touch this, usually.
         
     | 
| 
       185 
178 
     | 
    
         
             
                attr_reader :stowbuffer
         
     | 
| 
      
 179 
     | 
    
         
            +
                # @private
         
     | 
| 
       186 
180 
     | 
    
         
             
                # The meta-information hash used by assemble! No need to touch this, usually.
         
     | 
| 
       187 
181 
     | 
    
         
             
                attr_reader :metabuffer
         
     | 
| 
       188 
     | 
    
         
            -
                # :startdoc:
         
     | 
| 
       189 
182 
     | 
    
         | 
| 
       190 
183 
     | 
    
         
             
                # Convert obj to on-the-wire format.
         
     | 
| 
       191 
184 
     | 
    
         
             
                def to obj
         
     | 
| 
         @@ -212,12 +205,6 @@ module Arpie 
     | 
|
| 
       212 
205 
     | 
    
         
             
                  0
         
     | 
| 
       213 
206 
     | 
    
         
             
                end
         
     | 
| 
       214 
207 
     | 
    
         | 
| 
       215 
     | 
    
         
            -
                # Call this within Protocol#from to reparse the current
         
     | 
| 
       216 
     | 
    
         
            -
                # message.
         
     | 
| 
       217 
     | 
    
         
            -
                def again!
         
     | 
| 
       218 
     | 
    
         
            -
                  raise ETryAgain
         
     | 
| 
       219 
     | 
    
         
            -
                end
         
     | 
| 
       220 
     | 
    
         
            -
             
     | 
| 
       221 
208 
     | 
    
         
             
                # Stow away a message in this protocols buffer for later reassembly.
         
     | 
| 
       222 
209 
     | 
    
         
             
                # Optional argument: a token if you are planning to reassemble multiple
         
     | 
| 
       223 
210 
     | 
    
         
             
                # interleaved/fragmented message streams.
         
     | 
| 
         @@ -338,16 +325,13 @@ module Arpie 
     | 
|
| 
       338 
325 
     | 
    
         
             
              # A protocol which encodes objects into YAML representation.
         
     | 
| 
       339 
326 
     | 
    
         
             
              # Messages are arbitary yaml-encodable objects.
         
     | 
| 
       340 
327 
     | 
    
         
             
              class YAMLProtocol < Protocol
         
     | 
| 
       341 
     | 
    
         
            -
                CAN_SEPARATE_MESSAGES = true
         
     | 
| 
       342 
     | 
    
         
            -
             
     | 
| 
       343 
328 
     | 
    
         
             
                def to object
         
     | 
| 
       344 
     | 
    
         
            -
                  yield YAML.dump(object) 
     | 
| 
      
 329 
     | 
    
         
            +
                  yield YAML.dump(object)
         
     | 
| 
       345 
330 
     | 
    
         
             
                end
         
     | 
| 
       346 
331 
     | 
    
         | 
| 
       347 
332 
     | 
    
         
             
                def from binary
         
     | 
| 
       348 
     | 
    
         
            -
                   
     | 
| 
       349 
     | 
    
         
            -
                   
     | 
| 
       350 
     | 
    
         
            -
                  4 + index
         
     | 
| 
      
 333 
     | 
    
         
            +
                  yield YAML.load(binary)
         
     | 
| 
      
 334 
     | 
    
         
            +
                  binary.size
         
     | 
| 
       351 
335 
     | 
    
         
             
                end
         
     | 
| 
       352 
336 
     | 
    
         
             
              end
         
     | 
| 
       353 
337 
     | 
    
         | 
    
        data/spec/binary_spec.rb
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require File.join(File.dirname(__FILE__), 'spec_helper')
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            describe  
     | 
| 
      
 3 
     | 
    
         
            +
            describe Arpie::Binary do
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
              describe "empty:" do subject {
         
     | 
| 
       6 
6 
     | 
    
         
             
                [
         
     | 
| 
         @@ -9,7 +9,7 @@ describe "Binary" do 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  ""
         
     | 
| 
       10 
10 
     | 
    
         
             
                ]
         
     | 
| 
       11 
11 
     | 
    
         
             
              }
         
     | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
      
 12 
     | 
    
         
            +
                include_examples "Binary Tests"
         
     | 
| 
       13 
13 
     | 
    
         
             
              end
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
              describe "basic sanity:" do subject {
         
     | 
| 
         @@ -24,7 +24,7 @@ describe "Binary" do 
     | 
|
| 
       24 
24 
     | 
    
         
             
                ]
         
     | 
| 
       25 
25 
     | 
    
         
             
              }
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                 
     | 
| 
      
 27 
     | 
    
         
            +
                include_examples "Binary Tests with data"
         
     | 
| 
       28 
28 
     | 
    
         
             
              end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
              describe ".virtual:" do subject {
         
     | 
| 
         @@ -32,18 +32,26 @@ describe "Binary" do 
     | 
|
| 
       32 
32 
     | 
    
         
             
                  Class.new(Binary) do
         
     | 
| 
       33 
33 
     | 
    
         
             
                    field :a, :uint8
         
     | 
| 
       34 
34 
     | 
    
         
             
                    field :b, :uint8
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       35 
36 
     | 
    
         
             
                    virtual :c, :uint8 do |o| o.a * o.b end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                    v :d, :uint8 do |o| 1 + o.c end
         
     | 
| 
       36 
39 
     | 
    
         
             
                  end,
         
     | 
| 
       37 
40 
     | 
    
         
             
                  [1, 2].pack("CC")
         
     | 
| 
       38 
41 
     | 
    
         
             
                ]
         
     | 
| 
       39 
42 
     | 
    
         
             
              }
         
     | 
| 
       40 
43 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                it_should_behave_like "Binary Tests with data"
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
44 
     | 
    
         
             
                it "evaluates the block given" do
         
     | 
| 
       44 
45 
     | 
    
         
             
                  b, co = @c.from(@d)
         
     | 
| 
       45 
46 
     | 
    
         
             
                  b.c.should == b.a * b.b
         
     | 
| 
       46 
47 
     | 
    
         
             
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                it "evaluates nested virtuals" do
         
     | 
| 
      
 50 
     | 
    
         
            +
                  b, co = @c.from(@d)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  b.d.should == b.c + 1
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                include_examples "Binary Tests with data"
         
     | 
| 
       47 
55 
     | 
    
         
             
              end
         
     | 
| 
       48 
56 
     | 
    
         | 
| 
       49 
57 
     | 
    
         
             
              describe ".aliases:" do subject {
         
     | 
| 
         @@ -58,7 +66,7 @@ describe "Binary" do 
     | 
|
| 
       58 
66 
     | 
    
         
             
                ]
         
     | 
| 
       59 
67 
     | 
    
         
             
              }
         
     | 
| 
       60 
68 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
                 
     | 
| 
      
 69 
     | 
    
         
            +
                include_examples "Binary Tests with data"
         
     | 
| 
       62 
70 
     | 
    
         
             
              end
         
     | 
| 
       63 
71 
     | 
    
         | 
| 
       64 
72 
     | 
    
         
             
              describe ":default:" do subject {
         
     | 
| 
         @@ -72,8 +80,6 @@ describe "Binary" do 
     | 
|
| 
       72 
80 
     | 
    
         
             
                ]
         
     | 
| 
       73 
81 
     | 
    
         
             
              }
         
     | 
| 
       74 
82 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
                it_should_behave_like "Binary Tests with data"
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
83 
     | 
    
         
             
                it "does not use the default when a value was read" do
         
     | 
| 
       78 
84 
     | 
    
         
             
                  b, con = @c.from([1, 2].pack("CC"))
         
     | 
| 
       79 
85 
     | 
    
         
             
                  b.a.should == 1
         
     | 
| 
         @@ -86,7 +92,106 @@ describe "Binary" do 
     | 
|
| 
       86 
92 
     | 
    
         
             
                  b.b.should == 5
         
     | 
| 
       87 
93 
     | 
    
         
             
                end
         
     | 
| 
       88 
94 
     | 
    
         | 
| 
      
 95 
     | 
    
         
            +
                it "uses the default for new binaries" do
         
     | 
| 
      
 96 
     | 
    
         
            +
                  new = @c.new
         
     | 
| 
      
 97 
     | 
    
         
            +
                  new.b.should == 5
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                include_examples "Binary Tests with data"
         
     | 
| 
       89 
101 
     | 
    
         
             
              end
         
     | 
| 
       90 
102 
     | 
    
         | 
| 
      
 103 
     | 
    
         
            +
              describe ":fixed:" do subject {
         
     | 
| 
      
 104 
     | 
    
         
            +
                [
         
     | 
| 
      
 105 
     | 
    
         
            +
                  Class.new(Binary) do
         
     | 
| 
      
 106 
     | 
    
         
            +
                    field :a, :fixed, :value => "abc"
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end,
         
     | 
| 
      
 108 
     | 
    
         
            +
                  ["abc"].pack("a*")
         
     | 
| 
      
 109 
     | 
    
         
            +
                ]
         
     | 
| 
      
 110 
     | 
    
         
            +
              }
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                it "does not use the default for new binaries when using :fixed" do
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @c.new.a.should == nil
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
       91 
115 
     | 
    
         | 
| 
      
 116 
     | 
    
         
            +
                it "fails on parsing invalid values" do
         
     | 
| 
      
 117 
     | 
    
         
            +
                  proc { @c.from("abd") }.should raise_error Arpie::StreamError
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                it "fails on setting invalid values" do
         
     | 
| 
      
 121 
     | 
    
         
            +
                  proc {
         
     | 
| 
      
 122 
     | 
    
         
            +
                    c = @c.new
         
     | 
| 
      
 123 
     | 
    
         
            +
                    c.a = "abd"
         
     | 
| 
      
 124 
     | 
    
         
            +
                    c.to
         
     | 
| 
      
 125 
     | 
    
         
            +
                  }.should raise_error Arpie::StreamError
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                include_examples "Binary Tests with data"
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              describe "static:" do subject {
         
     | 
| 
      
 132 
     | 
    
         
            +
                [
         
     | 
| 
      
 133 
     | 
    
         
            +
                  Class.new(Binary) do
         
     | 
| 
      
 134 
     | 
    
         
            +
                    static :a, "abc"
         
     | 
| 
      
 135 
     | 
    
         
            +
                  end,
         
     | 
| 
      
 136 
     | 
    
         
            +
                  ["abc"].pack("a*")
         
     | 
| 
      
 137 
     | 
    
         
            +
                ]
         
     | 
| 
      
 138 
     | 
    
         
            +
              }
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                it "uses the default for new binaries" do
         
     | 
| 
      
 141 
     | 
    
         
            +
                  new = @c.new.to.should == "abc"
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                it "fails on parsing invalid values" do
         
     | 
| 
      
 145 
     | 
    
         
            +
                  proc { @c.from("abd") }.should raise_error Arpie::StreamError
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                it "fails on setting invalid values" do
         
     | 
| 
      
 149 
     | 
    
         
            +
                  proc {
         
     | 
| 
      
 150 
     | 
    
         
            +
                    c = @c.new
         
     | 
| 
      
 151 
     | 
    
         
            +
                    c.a = "abd"
         
     | 
| 
      
 152 
     | 
    
         
            +
                    c.to
         
     | 
| 
      
 153 
     | 
    
         
            +
                  }.should raise_error Arpie::StreamError
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                include_examples "Binary Tests with data"
         
     | 
| 
      
 157 
     | 
    
         
            +
              end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
              describe "mod:" do
         
     | 
| 
      
 160 
     | 
    
         
            +
                specify {
         
     | 
| 
      
 161 
     | 
    
         
            +
                  klass = Class.new(Binary) do
         
     | 
| 
      
 162 
     | 
    
         
            +
                    uint8 :int, :mod => 1
         
     | 
| 
      
 163 
     | 
    
         
            +
                    string :test, :sizeof => :uint8, :sizeof_opts => { :mod => -1 }
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                  b, read = klass.from("\x01\x05abcde")
         
     | 
| 
      
 167 
     | 
    
         
            +
                  b.int.should == 2
         
     | 
| 
      
 168 
     | 
    
         
            +
                  b.test.should == "abcd"
         
     | 
| 
      
 169 
     | 
    
         
            +
                  read.should == 6
         
     | 
| 
      
 170 
     | 
    
         
            +
                }
         
     | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
              describe "short notation" do
         
     | 
| 
      
 174 
     | 
    
         
            +
                describe "invalid fields" do
         
     | 
| 
      
 175 
     | 
    
         
            +
                  specify do
         
     | 
| 
      
 176 
     | 
    
         
            +
                    proc {
         
     | 
| 
      
 177 
     | 
    
         
            +
                      Class.new(Binary) do
         
     | 
| 
      
 178 
     | 
    
         
            +
                        invalid :xy
         
     | 
| 
      
 179 
     | 
    
         
            +
                      end
         
     | 
| 
      
 180 
     | 
    
         
            +
                    }.should raise_error ArgumentError
         
     | 
| 
      
 181 
     | 
    
         
            +
                  end
         
     | 
| 
      
 182 
     | 
    
         
            +
                end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                describe "simple types" do
         
     | 
| 
      
 185 
     | 
    
         
            +
                  subject {
         
     | 
| 
      
 186 
     | 
    
         
            +
                    [
         
     | 
| 
      
 187 
     | 
    
         
            +
                      Class.new(Binary) do
         
     | 
| 
      
 188 
     | 
    
         
            +
                        bytes :a, :length => 5
         
     | 
| 
      
 189 
     | 
    
         
            +
                      end,
         
     | 
| 
      
 190 
     | 
    
         
            +
                      ["abc01"].pack("a5")
         
     | 
| 
      
 191 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 192 
     | 
    
         
            +
                  }
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  include_examples "Binary Tests with data"
         
     | 
| 
      
 195 
     | 
    
         
            +
                end
         
     | 
| 
      
 196 
     | 
    
         
            +
              end
         
     | 
| 
       92 
197 
     | 
    
         
             
            end
         
     |