tmm1-amqp 0.5.1
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/README +62 -0
 - data/examples/clock.rb +56 -0
 - data/examples/hashtable.rb +52 -0
 - data/examples/pingpong.rb +45 -0
 - data/examples/primes-forked.rb +63 -0
 - data/examples/primes-processes.rb +135 -0
 - data/examples/primes-simple.rb +19 -0
 - data/examples/primes-threaded.rb +49 -0
 - data/examples/primes.rb +99 -0
 - data/examples/simple.rb +77 -0
 - data/examples/stocks.rb +56 -0
 - data/lib/amqp.rb +14 -0
 - data/lib/amqp/buffer.rb +395 -0
 - data/lib/amqp/client.rb +135 -0
 - data/lib/amqp/frame.rb +124 -0
 - data/lib/amqp/protocol.rb +181 -0
 - data/lib/amqp/spec.rb +818 -0
 - data/lib/emfork.rb +67 -0
 - data/lib/mq.rb +133 -0
 - data/lib/mq/exchange.rb +36 -0
 - data/lib/mq/queue.rb +52 -0
 - data/lib/mq/rpc.rb +51 -0
 - data/protocol/amqp-0.8.json +606 -0
 - data/protocol/amqp-0.8.xml +3908 -0
 - data/protocol/codegen.rb +172 -0
 - data/protocol/doc.txt +281 -0
 - metadata +86 -0
 
    
        data/examples/primes.rb
    ADDED
    
    | 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $:.unshift File.dirname(__FILE__) + '/../lib'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mq'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # check MAX numbers for prime-ness
         
     | 
| 
      
 5 
     | 
    
         
            +
            MAX = 1000
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # logging
         
     | 
| 
      
 8 
     | 
    
         
            +
            def log *args
         
     | 
| 
      
 9 
     | 
    
         
            +
              p args
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            # spawn workers
         
     | 
| 
      
 13 
     | 
    
         
            +
            workers = ARGV[0] ? (Integer(ARGV[0]) rescue 1) : 1
         
     | 
| 
      
 14 
     | 
    
         
            +
            EM.fork(workers) do
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              log MQ.id, :started
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              class Fixnum
         
     | 
| 
      
 19 
     | 
    
         
            +
                def prime?
         
     | 
| 
      
 20 
     | 
    
         
            +
                  ('1' * self) !~ /^1?$|^(11+?)\1+$/
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              class PrimeChecker
         
     | 
| 
      
 25 
     | 
    
         
            +
                def is_prime? number
         
     | 
| 
      
 26 
     | 
    
         
            +
                  log "prime checker #{MQ.id}", :prime?, number
         
     | 
| 
      
 27 
     | 
    
         
            +
                  number.prime?
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              MQ.rpc('prime checker', PrimeChecker.new)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            # use workers to check which numbers are prime
         
     | 
| 
      
 36 
     | 
    
         
            +
            EM.run{
         
     | 
| 
      
 37 
     | 
    
         
            +
              
         
     | 
| 
      
 38 
     | 
    
         
            +
              prime_checker = MQ.rpc('prime checker')
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              (10_000...(10_000+MAX)).each do |num|
         
     | 
| 
      
 41 
     | 
    
         
            +
                log :checking, num
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                prime_checker.is_prime?(num) { |is_prime|
         
     | 
| 
      
 44 
     | 
    
         
            +
                  log :prime?, num, is_prime
         
     | 
| 
      
 45 
     | 
    
         
            +
                  (@primes||=[]) << num if is_prime
         
     | 
| 
      
 46 
     | 
    
         
            +
                  
         
     | 
| 
      
 47 
     | 
    
         
            +
                  if (@responses = (@responses || 0) + 1) == MAX
         
     | 
| 
      
 48 
     | 
    
         
            +
                    log :primes=, @primes
         
     | 
| 
      
 49 
     | 
    
         
            +
                    EM.stop_event_loop
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                }
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
              
         
     | 
| 
      
 55 
     | 
    
         
            +
            }
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            __END__
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            $ uname -a
         
     | 
| 
      
 60 
     | 
    
         
            +
            Linux gc 2.6.24-ARCH #1 SMP PREEMPT Sun Mar 30 10:50:22 CEST 2008 x86_64 Intel(R) Xeon(R) CPU X3220 @ 2.40GHz GenuineIntel GNU/Linux
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            $ cat /proc/cpuinfo | grep processor | wc -l
         
     | 
| 
      
 63 
     | 
    
         
            +
            4
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            $ time ruby primes-simple.rb 
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            real  0m16.055s
         
     | 
| 
      
 68 
     | 
    
         
            +
            user  0m16.052s
         
     | 
| 
      
 69 
     | 
    
         
            +
            sys 0m0.000s
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            $ time ruby primes.rb 1 >/dev/null
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            real  0m18.278s
         
     | 
| 
      
 74 
     | 
    
         
            +
            user  0m0.993s
         
     | 
| 
      
 75 
     | 
    
         
            +
            sys 0m0.027s
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            $ time ruby primes.rb 2 >/dev/null
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            real  0m17.316s
         
     | 
| 
      
 80 
     | 
    
         
            +
            user  0m0.967s
         
     | 
| 
      
 81 
     | 
    
         
            +
            sys 0m0.053s
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            $ time ruby primes.rb 4 >/dev/null
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            real  0m8.229s
         
     | 
| 
      
 86 
     | 
    
         
            +
            user  0m1.010s
         
     | 
| 
      
 87 
     | 
    
         
            +
            sys 0m0.030s
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            $ time ruby primes.rb 8 >/dev/null
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            real  0m5.893s
         
     | 
| 
      
 92 
     | 
    
         
            +
            user  0m1.023s
         
     | 
| 
      
 93 
     | 
    
         
            +
            sys 0m0.050s
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            $ time ruby primes.rb 16 >/dev/null
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            real  0m5.601s
         
     | 
| 
      
 98 
     | 
    
         
            +
            user  0m0.990s
         
     | 
| 
      
 99 
     | 
    
         
            +
            sys 0m0.043s
         
     | 
    
        data/examples/simple.rb
    ADDED
    
    | 
         @@ -0,0 +1,77 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $:.unshift File.dirname(__FILE__) + '/../lib'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'amqp'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module SimpleClient
         
     | 
| 
      
 5 
     | 
    
         
            +
              def process_frame frame
         
     | 
| 
      
 6 
     | 
    
         
            +
                case frame
         
     | 
| 
      
 7 
     | 
    
         
            +
                when Frame::Body
         
     | 
| 
      
 8 
     | 
    
         
            +
                  EM.stop_event_loop
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                when Frame::Method
         
     | 
| 
      
 11 
     | 
    
         
            +
                  case method = frame.payload
         
     | 
| 
      
 12 
     | 
    
         
            +
                  when Protocol::Connection::Start
         
     | 
| 
      
 13 
     | 
    
         
            +
                    send Protocol::Connection::StartOk.new({:platform => 'Ruby/EventMachine',
         
     | 
| 
      
 14 
     | 
    
         
            +
                                                            :product => 'AMQP',
         
     | 
| 
      
 15 
     | 
    
         
            +
                                                            :information => 'http://github.com/tmm1/amqp',
         
     | 
| 
      
 16 
     | 
    
         
            +
                                                            :version => '0.1.0'},
         
     | 
| 
      
 17 
     | 
    
         
            +
                                                           'AMQPLAIN',
         
     | 
| 
      
 18 
     | 
    
         
            +
                                                           {:LOGIN => 'guest',
         
     | 
| 
      
 19 
     | 
    
         
            +
                                                            :PASSWORD => 'guest'},
         
     | 
| 
      
 20 
     | 
    
         
            +
                                                           'en_US')
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  when Protocol::Connection::Tune
         
     | 
| 
      
 23 
     | 
    
         
            +
                    send Protocol::Connection::TuneOk.new(:channel_max => 0,
         
     | 
| 
      
 24 
     | 
    
         
            +
                                                          :frame_max => 131072,
         
     | 
| 
      
 25 
     | 
    
         
            +
                                                          :heartbeat => 0)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    send Protocol::Connection::Open.new(:virtual_host => '/',
         
     | 
| 
      
 28 
     | 
    
         
            +
                                                        :capabilities => '',
         
     | 
| 
      
 29 
     | 
    
         
            +
                                                        :insist => false)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  when Protocol::Connection::OpenOk
         
     | 
| 
      
 32 
     | 
    
         
            +
                    send Protocol::Channel::Open.new, :channel => 1
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  when Protocol::Channel::OpenOk
         
     | 
| 
      
 35 
     | 
    
         
            +
                    send Protocol::Access::Request.new(:realm => '/data',
         
     | 
| 
      
 36 
     | 
    
         
            +
                                                       :read => true,
         
     | 
| 
      
 37 
     | 
    
         
            +
                                                       :write => true,
         
     | 
| 
      
 38 
     | 
    
         
            +
                                                       :active => true), :channel => 1
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  when Protocol::Access::RequestOk
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @ticket = method.ticket
         
     | 
| 
      
 42 
     | 
    
         
            +
                    send Protocol::Queue::Declare.new(:ticket => @ticket,
         
     | 
| 
      
 43 
     | 
    
         
            +
                                                      :queue => '',
         
     | 
| 
      
 44 
     | 
    
         
            +
                                                      :exclusive => false,
         
     | 
| 
      
 45 
     | 
    
         
            +
                                                      :auto_delete => true), :channel => 1
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  when Protocol::Queue::DeclareOk
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @queue = method.queue
         
     | 
| 
      
 49 
     | 
    
         
            +
                    send Protocol::Queue::Bind.new(:ticket => @ticket,
         
     | 
| 
      
 50 
     | 
    
         
            +
                                                   :queue => @queue,
         
     | 
| 
      
 51 
     | 
    
         
            +
                                                   :exchange => '',
         
     | 
| 
      
 52 
     | 
    
         
            +
                                                   :routing_key => 'test_route'), :channel => 1
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  when Protocol::Queue::BindOk
         
     | 
| 
      
 55 
     | 
    
         
            +
                    send Protocol::Basic::Consume.new(:ticket => @ticket,
         
     | 
| 
      
 56 
     | 
    
         
            +
                                                      :queue => @queue,
         
     | 
| 
      
 57 
     | 
    
         
            +
                                                      :no_local => false,
         
     | 
| 
      
 58 
     | 
    
         
            +
                                                      :no_ack => true), :channel => 1
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  when Protocol::Basic::ConsumeOk
         
     | 
| 
      
 61 
     | 
    
         
            +
                    data = "this is a test!"
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    send Protocol::Basic::Publish.new(:ticket => @ticket,
         
     | 
| 
      
 64 
     | 
    
         
            +
                                                      :exchange => '',
         
     | 
| 
      
 65 
     | 
    
         
            +
                                                      :routing_key => 'test_route'), :channel => 1
         
     | 
| 
      
 66 
     | 
    
         
            +
                    send Protocol::Header.new(Protocol::Basic, data.length, :content_type => 'application/octet-stream',
         
     | 
| 
      
 67 
     | 
    
         
            +
                                                                            :delivery_mode => 1,
         
     | 
| 
      
 68 
     | 
    
         
            +
                                                                            :priority => 0), :channel => 1
         
     | 
| 
      
 69 
     | 
    
         
            +
                    send Frame::Body.new(data), :channel => 1
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            AMQP.logging = true
         
     | 
| 
      
 76 
     | 
    
         
            +
            AMQP.client = SimpleClient
         
     | 
| 
      
 77 
     | 
    
         
            +
            AMQP.start
         
     | 
    
        data/examples/stocks.rb
    ADDED
    
    | 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $:.unshift File.dirname(__FILE__) + '/../lib'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mq'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            EM.run{
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def log *args
         
     | 
| 
      
 7 
     | 
    
         
            +
                p [ Time.now, *args ]
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # AMQP.logging = true
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              EM.add_periodic_timer(1){
         
     | 
| 
      
 13 
     | 
    
         
            +
                puts
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                log :publishing, 'stock.usd.appl', price = 170+rand(1000)/100.0
         
     | 
| 
      
 16 
     | 
    
         
            +
                MQ.topic.publish(price, :key => 'stock.usd.appl', :headers => {:symbol => 'appl'})
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                log :publishing, 'stock.usd.msft', price = 22+rand(500)/100.0
         
     | 
| 
      
 19 
     | 
    
         
            +
                MQ.topic.publish(price, :key => 'stock.usd.msft', :headers => {:symbol => 'msft'})
         
     | 
| 
      
 20 
     | 
    
         
            +
              }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              Thread.new{
         
     | 
| 
      
 23 
     | 
    
         
            +
                amq = MQ.new
         
     | 
| 
      
 24 
     | 
    
         
            +
                amq.queue('apple stock').bind(amq.topic, :key => 'stock.usd.appl').subscribe{ |price|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  log 'apple stock', price
         
     | 
| 
      
 26 
     | 
    
         
            +
                }
         
     | 
| 
      
 27 
     | 
    
         
            +
              }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              Thread.new{
         
     | 
| 
      
 30 
     | 
    
         
            +
                amq = MQ.new
         
     | 
| 
      
 31 
     | 
    
         
            +
                amq.queue('us stocks').bind(amq.topic, :key => 'stock.usd.*').subscribe{ |info, price|
         
     | 
| 
      
 32 
     | 
    
         
            +
                  log 'us stock', info.headers[:symbol], price
         
     | 
| 
      
 33 
     | 
    
         
            +
                }
         
     | 
| 
      
 34 
     | 
    
         
            +
              }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            __END__
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            [Thu Jul 17 14:51:07 -0700 2008, :publishing, "stock.usd.appl", 170.84]
         
     | 
| 
      
 41 
     | 
    
         
            +
            [Thu Jul 17 14:51:07 -0700 2008, :publishing, "stock.usd.msft", 23.68]
         
     | 
| 
      
 42 
     | 
    
         
            +
            [Thu Jul 17 14:51:07 -0700 2008, "apple stock", "170.84"]
         
     | 
| 
      
 43 
     | 
    
         
            +
            [Thu Jul 17 14:51:07 -0700 2008, "us stock", "appl", "170.84"]
         
     | 
| 
      
 44 
     | 
    
         
            +
            [Thu Jul 17 14:51:07 -0700 2008, "us stock", "msft", "23.68"]
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            [Thu Jul 17 14:51:08 -0700 2008, :publishing, "stock.usd.appl", 173.61]
         
     | 
| 
      
 47 
     | 
    
         
            +
            [Thu Jul 17 14:51:08 -0700 2008, :publishing, "stock.usd.msft", 25.8]
         
     | 
| 
      
 48 
     | 
    
         
            +
            [Thu Jul 17 14:51:08 -0700 2008, "apple stock", "173.61"]
         
     | 
| 
      
 49 
     | 
    
         
            +
            [Thu Jul 17 14:51:08 -0700 2008, "us stock", "appl", "173.61"]
         
     | 
| 
      
 50 
     | 
    
         
            +
            [Thu Jul 17 14:51:08 -0700 2008, "us stock", "msft", "25.8"]
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            [Thu Jul 17 14:51:09 -0700 2008, :publishing, "stock.usd.appl", 173.94]
         
     | 
| 
      
 53 
     | 
    
         
            +
            [Thu Jul 17 14:51:09 -0700 2008, :publishing, "stock.usd.msft", 24.88]
         
     | 
| 
      
 54 
     | 
    
         
            +
            [Thu Jul 17 14:51:09 -0700 2008, "apple stock", "173.94"]
         
     | 
| 
      
 55 
     | 
    
         
            +
            [Thu Jul 17 14:51:09 -0700 2008, "us stock", "appl", "173.94"]
         
     | 
| 
      
 56 
     | 
    
         
            +
            [Thu Jul 17 14:51:09 -0700 2008, "us stock", "msft", "24.88"]
         
     | 
    
        data/lib/amqp.rb
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module AMQP
         
     | 
| 
      
 2 
     | 
    
         
            +
              DIR = File.expand_path(File.dirname(File.expand_path(__FILE__)))
         
     | 
| 
      
 3 
     | 
    
         
            +
              
         
     | 
| 
      
 4 
     | 
    
         
            +
              $:.unshift DIR
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
              %w[ buffer spec protocol frame client ].each do |file|
         
     | 
| 
      
 7 
     | 
    
         
            +
                require "amqp/#{file}"
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                @logging = false
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :logging
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/amqp/buffer.rb
    ADDED
    
    | 
         @@ -0,0 +1,395 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            if [].map.respond_to? :with_index
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Array
         
     | 
| 
      
 3 
     | 
    
         
            +
                def enum_with_index
         
     | 
| 
      
 4 
     | 
    
         
            +
                  each.with_index
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
            else
         
     | 
| 
      
 8 
     | 
    
         
            +
              require 'enumerator'
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            module AMQP
         
     | 
| 
      
 12 
     | 
    
         
            +
              class Buffer
         
     | 
| 
      
 13 
     | 
    
         
            +
                class Overflow < Exception; end
         
     | 
| 
      
 14 
     | 
    
         
            +
                class InvalidType < Exception; end
         
     | 
| 
      
 15 
     | 
    
         
            +
                
         
     | 
| 
      
 16 
     | 
    
         
            +
                def initialize data = ''
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @data = data
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @pos = 0
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                attr_reader :pos
         
     | 
| 
      
 22 
     | 
    
         
            +
                
         
     | 
| 
      
 23 
     | 
    
         
            +
                def data
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @data.clone
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
                alias :contents :data
         
     | 
| 
      
 27 
     | 
    
         
            +
                alias :to_s :data
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def << data
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @data << data.to_s
         
     | 
| 
      
 31 
     | 
    
         
            +
                  self
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
                
         
     | 
| 
      
 34 
     | 
    
         
            +
                def length
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @data.length
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
                
         
     | 
| 
      
 38 
     | 
    
         
            +
                def empty?
         
     | 
| 
      
 39 
     | 
    
         
            +
                  pos == length
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
                
         
     | 
| 
      
 42 
     | 
    
         
            +
                def rewind
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @pos = 0
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                
         
     | 
| 
      
 46 
     | 
    
         
            +
                def read_properties *types
         
     | 
| 
      
 47 
     | 
    
         
            +
                  types.shift if types.first == :properties
         
     | 
| 
      
 48 
     | 
    
         
            +
                  
         
     | 
| 
      
 49 
     | 
    
         
            +
                  i = 0
         
     | 
| 
      
 50 
     | 
    
         
            +
                  values = []
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  while props = read(:short)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    (0..14).each do |n|
         
     | 
| 
      
 54 
     | 
    
         
            +
                      # no more property types
         
     | 
| 
      
 55 
     | 
    
         
            +
                      break unless types[i]
         
     | 
| 
      
 56 
     | 
    
         
            +
                      
         
     | 
| 
      
 57 
     | 
    
         
            +
                      # if flag is set
         
     | 
| 
      
 58 
     | 
    
         
            +
                      if props & (1<<(15-n)) != 0
         
     | 
| 
      
 59 
     | 
    
         
            +
                        if types[i] == :bit
         
     | 
| 
      
 60 
     | 
    
         
            +
                          # bit values exist in flags only
         
     | 
| 
      
 61 
     | 
    
         
            +
                          values << true
         
     | 
| 
      
 62 
     | 
    
         
            +
                        else
         
     | 
| 
      
 63 
     | 
    
         
            +
                          # save type name for later reading
         
     | 
| 
      
 64 
     | 
    
         
            +
                          values << types[i]
         
     | 
| 
      
 65 
     | 
    
         
            +
                        end
         
     | 
| 
      
 66 
     | 
    
         
            +
                      else
         
     | 
| 
      
 67 
     | 
    
         
            +
                        # property not set or is false bit
         
     | 
| 
      
 68 
     | 
    
         
            +
                        values << (types[i] == :bit ? false : nil)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                      i+=1
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    # bit(0) == 0 means no more property flags
         
     | 
| 
      
 75 
     | 
    
         
            +
                    break unless props & 1 == 1
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  values.map do |value|
         
     | 
| 
      
 79 
     | 
    
         
            +
                    value.is_a?(Symbol) ? read(value) : value
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                def read *types
         
     | 
| 
      
 84 
     | 
    
         
            +
                  if types.first == :properties
         
     | 
| 
      
 85 
     | 
    
         
            +
                    return read_properties(*types)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  values = types.map do |type|
         
     | 
| 
      
 89 
     | 
    
         
            +
                    case type
         
     | 
| 
      
 90 
     | 
    
         
            +
                    when :octet
         
     | 
| 
      
 91 
     | 
    
         
            +
                      _read(1, 'C')
         
     | 
| 
      
 92 
     | 
    
         
            +
                    when :short
         
     | 
| 
      
 93 
     | 
    
         
            +
                      _read(2, 'n')
         
     | 
| 
      
 94 
     | 
    
         
            +
                    when :long
         
     | 
| 
      
 95 
     | 
    
         
            +
                      _read(4, 'N')
         
     | 
| 
      
 96 
     | 
    
         
            +
                    when :longlong
         
     | 
| 
      
 97 
     | 
    
         
            +
                      upper, lower = _read(8, 'NN')
         
     | 
| 
      
 98 
     | 
    
         
            +
                      upper << 32 | lower
         
     | 
| 
      
 99 
     | 
    
         
            +
                    when :shortstr
         
     | 
| 
      
 100 
     | 
    
         
            +
                      _read read(:octet)
         
     | 
| 
      
 101 
     | 
    
         
            +
                    when :longstr
         
     | 
| 
      
 102 
     | 
    
         
            +
                      _read read(:long)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    when :timestamp
         
     | 
| 
      
 104 
     | 
    
         
            +
                      Time.at read(:longlong)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    when :table
         
     | 
| 
      
 106 
     | 
    
         
            +
                      t = Hash.new
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                      table = Buffer.new(read(:longstr))
         
     | 
| 
      
 109 
     | 
    
         
            +
                      until table.empty?
         
     | 
| 
      
 110 
     | 
    
         
            +
                        key, type = table.read(:shortstr, :octet)
         
     | 
| 
      
 111 
     | 
    
         
            +
                        key = key.intern
         
     | 
| 
      
 112 
     | 
    
         
            +
                        t[key] ||= case type
         
     | 
| 
      
 113 
     | 
    
         
            +
                                   when 83 # 'S'
         
     | 
| 
      
 114 
     | 
    
         
            +
                                     table.read(:longstr)
         
     | 
| 
      
 115 
     | 
    
         
            +
                                   when 73 # 'I'
         
     | 
| 
      
 116 
     | 
    
         
            +
                                     table.read(:long)
         
     | 
| 
      
 117 
     | 
    
         
            +
                                   when 68 # 'D'
         
     | 
| 
      
 118 
     | 
    
         
            +
                                     exp = table.read(:octet)
         
     | 
| 
      
 119 
     | 
    
         
            +
                                     num = table.read(:long)
         
     | 
| 
      
 120 
     | 
    
         
            +
                                     num / 10.0**exp
         
     | 
| 
      
 121 
     | 
    
         
            +
                                   when 84 # 'T'
         
     | 
| 
      
 122 
     | 
    
         
            +
                                     table.read(:timestamp)
         
     | 
| 
      
 123 
     | 
    
         
            +
                                   when 70 # 'F'
         
     | 
| 
      
 124 
     | 
    
         
            +
                                     table.read(:table)
         
     | 
| 
      
 125 
     | 
    
         
            +
                                   end
         
     | 
| 
      
 126 
     | 
    
         
            +
                      end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                      t
         
     | 
| 
      
 129 
     | 
    
         
            +
                    when :bit
         
     | 
| 
      
 130 
     | 
    
         
            +
                      if (@bits ||= []).empty?
         
     | 
| 
      
 131 
     | 
    
         
            +
                        val = read(:octet)
         
     | 
| 
      
 132 
     | 
    
         
            +
                        @bits = (0..7).map{|i| (val & 1<<i) != 0 }
         
     | 
| 
      
 133 
     | 
    
         
            +
                      end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                      @bits.shift
         
     | 
| 
      
 136 
     | 
    
         
            +
                    else
         
     | 
| 
      
 137 
     | 
    
         
            +
                      raise InvalidType, "Cannot read data of type #{type}"
         
     | 
| 
      
 138 
     | 
    
         
            +
                    end
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                  
         
     | 
| 
      
 141 
     | 
    
         
            +
                  types.size == 1 ? values.first : values
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
                
         
     | 
| 
      
 144 
     | 
    
         
            +
                def write type, data
         
     | 
| 
      
 145 
     | 
    
         
            +
                  case type
         
     | 
| 
      
 146 
     | 
    
         
            +
                  when :octet
         
     | 
| 
      
 147 
     | 
    
         
            +
                    _write(data, 'C')
         
     | 
| 
      
 148 
     | 
    
         
            +
                  when :short
         
     | 
| 
      
 149 
     | 
    
         
            +
                    _write(data, 'n')
         
     | 
| 
      
 150 
     | 
    
         
            +
                  when :long
         
     | 
| 
      
 151 
     | 
    
         
            +
                    _write(data, 'N')
         
     | 
| 
      
 152 
     | 
    
         
            +
                  when :longlong
         
     | 
| 
      
 153 
     | 
    
         
            +
                    lower =  data & 0xffffffff
         
     | 
| 
      
 154 
     | 
    
         
            +
                    upper = (data & ~0xffffffff) >> 32
         
     | 
| 
      
 155 
     | 
    
         
            +
                    _write([upper, lower], 'NN')
         
     | 
| 
      
 156 
     | 
    
         
            +
                  when :shortstr
         
     | 
| 
      
 157 
     | 
    
         
            +
                    data = (data || '').to_s
         
     | 
| 
      
 158 
     | 
    
         
            +
                    _write([data.length, data], 'Ca*')
         
     | 
| 
      
 159 
     | 
    
         
            +
                  when :longstr
         
     | 
| 
      
 160 
     | 
    
         
            +
                    if data.is_a? Hash
         
     | 
| 
      
 161 
     | 
    
         
            +
                      write(:table, data)
         
     | 
| 
      
 162 
     | 
    
         
            +
                    else
         
     | 
| 
      
 163 
     | 
    
         
            +
                      data = (data || '').to_s
         
     | 
| 
      
 164 
     | 
    
         
            +
                      _write([data.length, data], 'Na*')
         
     | 
| 
      
 165 
     | 
    
         
            +
                    end
         
     | 
| 
      
 166 
     | 
    
         
            +
                  when :timestamp
         
     | 
| 
      
 167 
     | 
    
         
            +
                    write(:longlong, data.to_i)
         
     | 
| 
      
 168 
     | 
    
         
            +
                  when :table
         
     | 
| 
      
 169 
     | 
    
         
            +
                    data ||= {}
         
     | 
| 
      
 170 
     | 
    
         
            +
                    write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
         
     | 
| 
      
 171 
     | 
    
         
            +
                                      table.write(:shortstr, key.to_s)
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                                      case value
         
     | 
| 
      
 174 
     | 
    
         
            +
                                      when String
         
     | 
| 
      
 175 
     | 
    
         
            +
                                        table.write(:octet, 83) # 'S'
         
     | 
| 
      
 176 
     | 
    
         
            +
                                        table.write(:longstr, value.to_s)
         
     | 
| 
      
 177 
     | 
    
         
            +
                                      when Fixnum
         
     | 
| 
      
 178 
     | 
    
         
            +
                                        table.write(:octet, 73) # 'I'
         
     | 
| 
      
 179 
     | 
    
         
            +
                                        table.write(:long, value)
         
     | 
| 
      
 180 
     | 
    
         
            +
                                      when Float
         
     | 
| 
      
 181 
     | 
    
         
            +
                                        table.write(:octet, 68) # 'D'
         
     | 
| 
      
 182 
     | 
    
         
            +
                                        # XXX there's gotta be a better way to do this..
         
     | 
| 
      
 183 
     | 
    
         
            +
                                        exp = value.to_s.split('.').last.length
         
     | 
| 
      
 184 
     | 
    
         
            +
                                        num = value * 10**exp
         
     | 
| 
      
 185 
     | 
    
         
            +
                                        table.write(:octet, exp)
         
     | 
| 
      
 186 
     | 
    
         
            +
                                        table.write(:long, num)
         
     | 
| 
      
 187 
     | 
    
         
            +
                                      when Time
         
     | 
| 
      
 188 
     | 
    
         
            +
                                        table.write(:octet, 84) # 'T'
         
     | 
| 
      
 189 
     | 
    
         
            +
                                        table.write(:timestamp, value)
         
     | 
| 
      
 190 
     | 
    
         
            +
                                      when Hash
         
     | 
| 
      
 191 
     | 
    
         
            +
                                        table.write(:octet, 70) # 'F'
         
     | 
| 
      
 192 
     | 
    
         
            +
                                        table.write(:table, value)
         
     | 
| 
      
 193 
     | 
    
         
            +
                                      end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                                      table
         
     | 
| 
      
 196 
     | 
    
         
            +
                                    end)
         
     | 
| 
      
 197 
     | 
    
         
            +
                  when :bit
         
     | 
| 
      
 198 
     | 
    
         
            +
                    [*data].to_enum(:each_slice, 8).each{|bits|
         
     | 
| 
      
 199 
     | 
    
         
            +
                      write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
         
     | 
| 
      
 200 
     | 
    
         
            +
                        byte |= 1<<i if bit
         
     | 
| 
      
 201 
     | 
    
         
            +
                        byte
         
     | 
| 
      
 202 
     | 
    
         
            +
                       })
         
     | 
| 
      
 203 
     | 
    
         
            +
                     }
         
     | 
| 
      
 204 
     | 
    
         
            +
                  when :properties
         
     | 
| 
      
 205 
     | 
    
         
            +
                    values = []
         
     | 
| 
      
 206 
     | 
    
         
            +
                    data.enum_with_index.inject(0) do |short, ((type, value), i)|
         
     | 
| 
      
 207 
     | 
    
         
            +
                      n = i % 15
         
     | 
| 
      
 208 
     | 
    
         
            +
                      last = i+1 == data.size
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                      if (n == 0 and i != 0) or last
         
     | 
| 
      
 211 
     | 
    
         
            +
                        if data.size > i+1
         
     | 
| 
      
 212 
     | 
    
         
            +
                          short |= 1<<0
         
     | 
| 
      
 213 
     | 
    
         
            +
                        elsif last and value
         
     | 
| 
      
 214 
     | 
    
         
            +
                          values << [type,value]
         
     | 
| 
      
 215 
     | 
    
         
            +
                          short |= 1<<(15-n)
         
     | 
| 
      
 216 
     | 
    
         
            +
                        end
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                        write(:short, short)
         
     | 
| 
      
 219 
     | 
    
         
            +
                        short = 0
         
     | 
| 
      
 220 
     | 
    
         
            +
                      end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                      if value and !last
         
     | 
| 
      
 223 
     | 
    
         
            +
                        values << [type,value] 
         
     | 
| 
      
 224 
     | 
    
         
            +
                        short |= 1<<(15-n)
         
     | 
| 
      
 225 
     | 
    
         
            +
                      end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                      short
         
     | 
| 
      
 228 
     | 
    
         
            +
                    end
         
     | 
| 
      
 229 
     | 
    
         
            +
                    
         
     | 
| 
      
 230 
     | 
    
         
            +
                    values.each do |type, value|
         
     | 
| 
      
 231 
     | 
    
         
            +
                      write(type, value) unless type == :bit
         
     | 
| 
      
 232 
     | 
    
         
            +
                    end
         
     | 
| 
      
 233 
     | 
    
         
            +
                  else
         
     | 
| 
      
 234 
     | 
    
         
            +
                    raise InvalidType, "Cannot write data of type #{type}"
         
     | 
| 
      
 235 
     | 
    
         
            +
                  end
         
     | 
| 
      
 236 
     | 
    
         
            +
                  
         
     | 
| 
      
 237 
     | 
    
         
            +
                  self
         
     | 
| 
      
 238 
     | 
    
         
            +
                end
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
                def extract
         
     | 
| 
      
 241 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 242 
     | 
    
         
            +
                    cur_data, cur_pos = @data.clone, @pos
         
     | 
| 
      
 243 
     | 
    
         
            +
                    yield self
         
     | 
| 
      
 244 
     | 
    
         
            +
                  rescue Overflow
         
     | 
| 
      
 245 
     | 
    
         
            +
                    @data, @pos = cur_data, cur_pos
         
     | 
| 
      
 246 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 247 
     | 
    
         
            +
                  end
         
     | 
| 
      
 248 
     | 
    
         
            +
                end
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
                def _read size, pack = nil
         
     | 
| 
      
 251 
     | 
    
         
            +
                  if @pos + size > length
         
     | 
| 
      
 252 
     | 
    
         
            +
                    raise Overflow
         
     | 
| 
      
 253 
     | 
    
         
            +
                  else
         
     | 
| 
      
 254 
     | 
    
         
            +
                    data = @data[@pos,size]
         
     | 
| 
      
 255 
     | 
    
         
            +
                    @data[@pos,size] = ''
         
     | 
| 
      
 256 
     | 
    
         
            +
                    if pack
         
     | 
| 
      
 257 
     | 
    
         
            +
                      data = data.unpack(pack)
         
     | 
| 
      
 258 
     | 
    
         
            +
                      data = data.pop if data.size == 1
         
     | 
| 
      
 259 
     | 
    
         
            +
                    end
         
     | 
| 
      
 260 
     | 
    
         
            +
                    data
         
     | 
| 
      
 261 
     | 
    
         
            +
                  end
         
     | 
| 
      
 262 
     | 
    
         
            +
                end
         
     | 
| 
      
 263 
     | 
    
         
            +
                
         
     | 
| 
      
 264 
     | 
    
         
            +
                def _write data, pack = nil
         
     | 
| 
      
 265 
     | 
    
         
            +
                  data = [*data].pack(pack) if pack
         
     | 
| 
      
 266 
     | 
    
         
            +
                  @data[@pos,0] = data
         
     | 
| 
      
 267 
     | 
    
         
            +
                  @pos += data.length
         
     | 
| 
      
 268 
     | 
    
         
            +
                end
         
     | 
| 
      
 269 
     | 
    
         
            +
              end
         
     | 
| 
      
 270 
     | 
    
         
            +
            end
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
            if $0 =~ /bacon/ or $0 == __FILE__
         
     | 
| 
      
 273 
     | 
    
         
            +
              require 'bacon'
         
     | 
| 
      
 274 
     | 
    
         
            +
              include AMQP
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
              describe Buffer do
         
     | 
| 
      
 277 
     | 
    
         
            +
                before do
         
     | 
| 
      
 278 
     | 
    
         
            +
                  @buf = Buffer.new
         
     | 
| 
      
 279 
     | 
    
         
            +
                end
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
                should 'have contents' do
         
     | 
| 
      
 282 
     | 
    
         
            +
                  @buf.contents.should == ''
         
     | 
| 
      
 283 
     | 
    
         
            +
                end
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                should 'initialize with data' do
         
     | 
| 
      
 286 
     | 
    
         
            +
                  @buf = Buffer.new('abc')
         
     | 
| 
      
 287 
     | 
    
         
            +
                  @buf.contents.should == 'abc'
         
     | 
| 
      
 288 
     | 
    
         
            +
                end
         
     | 
| 
      
 289 
     | 
    
         
            +
             
     | 
| 
      
 290 
     | 
    
         
            +
                should 'append raw data' do
         
     | 
| 
      
 291 
     | 
    
         
            +
                  @buf << 'abc'
         
     | 
| 
      
 292 
     | 
    
         
            +
                  @buf << 'def'
         
     | 
| 
      
 293 
     | 
    
         
            +
                  @buf.contents.should == 'abcdef'
         
     | 
| 
      
 294 
     | 
    
         
            +
                end
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
                should 'append other buffers' do
         
     | 
| 
      
 297 
     | 
    
         
            +
                  @buf << Buffer.new('abc')
         
     | 
| 
      
 298 
     | 
    
         
            +
                  @buf.data.should == 'abc'
         
     | 
| 
      
 299 
     | 
    
         
            +
                end
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
                should 'have a position' do
         
     | 
| 
      
 302 
     | 
    
         
            +
                  @buf.pos.should == 0
         
     | 
| 
      
 303 
     | 
    
         
            +
                end
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
                should 'have a length' do
         
     | 
| 
      
 306 
     | 
    
         
            +
                  @buf.length.should == 0
         
     | 
| 
      
 307 
     | 
    
         
            +
                  @buf << 'abc'
         
     | 
| 
      
 308 
     | 
    
         
            +
                  @buf.length.should == 3
         
     | 
| 
      
 309 
     | 
    
         
            +
                end
         
     | 
| 
      
 310 
     | 
    
         
            +
             
     | 
| 
      
 311 
     | 
    
         
            +
                should 'know the end' do
         
     | 
| 
      
 312 
     | 
    
         
            +
                  @buf.empty?.should == true
         
     | 
| 
      
 313 
     | 
    
         
            +
                end
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                should 'read and write data' do
         
     | 
| 
      
 316 
     | 
    
         
            +
                  @buf._write('abc')
         
     | 
| 
      
 317 
     | 
    
         
            +
                  @buf.rewind
         
     | 
| 
      
 318 
     | 
    
         
            +
                  @buf._read(2).should == 'ab'
         
     | 
| 
      
 319 
     | 
    
         
            +
                  @buf._read(1).should == 'c'
         
     | 
| 
      
 320 
     | 
    
         
            +
                end
         
     | 
| 
      
 321 
     | 
    
         
            +
             
     | 
| 
      
 322 
     | 
    
         
            +
                should 'raise on overflow' do
         
     | 
| 
      
 323 
     | 
    
         
            +
                  lambda{ @buf._read(1) }.should.raise Buffer::Overflow
         
     | 
| 
      
 324 
     | 
    
         
            +
                end
         
     | 
| 
      
 325 
     | 
    
         
            +
             
     | 
| 
      
 326 
     | 
    
         
            +
                should 'raise on invalid types' do
         
     | 
| 
      
 327 
     | 
    
         
            +
                  lambda{ @buf.read(:junk) }.should.raise Buffer::InvalidType
         
     | 
| 
      
 328 
     | 
    
         
            +
                  lambda{ @buf.write(:junk, 1) }.should.raise Buffer::InvalidType
         
     | 
| 
      
 329 
     | 
    
         
            +
                end
         
     | 
| 
      
 330 
     | 
    
         
            +
              
         
     | 
| 
      
 331 
     | 
    
         
            +
                { :octet => 0b10101010,
         
     | 
| 
      
 332 
     | 
    
         
            +
                  :short => 100,
         
     | 
| 
      
 333 
     | 
    
         
            +
                  :long => 100_000_000,
         
     | 
| 
      
 334 
     | 
    
         
            +
                  :longlong => 666_555_444_333_222_111,
         
     | 
| 
      
 335 
     | 
    
         
            +
                  :shortstr => 'hello',
         
     | 
| 
      
 336 
     | 
    
         
            +
                  :longstr => 'bye'*500,
         
     | 
| 
      
 337 
     | 
    
         
            +
                  :timestamp => time = Time.at(Time.now.to_i),
         
     | 
| 
      
 338 
     | 
    
         
            +
                  :table => { :this => 'is', :a => 'hash', :with => {:nested => 123, :and => time, :also => 123.456} },
         
     | 
| 
      
 339 
     | 
    
         
            +
                  :bit => true
         
     | 
| 
      
 340 
     | 
    
         
            +
                }.each do |type, value|
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                  should "read and write a #{type}" do
         
     | 
| 
      
 343 
     | 
    
         
            +
                    @buf.write(type, value)
         
     | 
| 
      
 344 
     | 
    
         
            +
                    @buf.rewind
         
     | 
| 
      
 345 
     | 
    
         
            +
                    @buf.read(type).should == value
         
     | 
| 
      
 346 
     | 
    
         
            +
                    @buf.should.be.empty
         
     | 
| 
      
 347 
     | 
    
         
            +
                  end
         
     | 
| 
      
 348 
     | 
    
         
            +
             
     | 
| 
      
 349 
     | 
    
         
            +
                end
         
     | 
| 
      
 350 
     | 
    
         
            +
                
         
     | 
| 
      
 351 
     | 
    
         
            +
                should 'read and write multiple bits' do
         
     | 
| 
      
 352 
     | 
    
         
            +
                  bits = [true, false, false, true, true, false, false, true, true, false]
         
     | 
| 
      
 353 
     | 
    
         
            +
                  @buf.write(:bit, bits)
         
     | 
| 
      
 354 
     | 
    
         
            +
                  @buf.write(:octet, 100)
         
     | 
| 
      
 355 
     | 
    
         
            +
                  
         
     | 
| 
      
 356 
     | 
    
         
            +
                  @buf.rewind
         
     | 
| 
      
 357 
     | 
    
         
            +
                  
         
     | 
| 
      
 358 
     | 
    
         
            +
                  bits.map do
         
     | 
| 
      
 359 
     | 
    
         
            +
                    @buf.read(:bit)
         
     | 
| 
      
 360 
     | 
    
         
            +
                  end.should == bits
         
     | 
| 
      
 361 
     | 
    
         
            +
                  @buf.read(:octet).should == 100
         
     | 
| 
      
 362 
     | 
    
         
            +
                end
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
      
 364 
     | 
    
         
            +
                should 'read and write properties' do
         
     | 
| 
      
 365 
     | 
    
         
            +
                  properties = ([
         
     | 
| 
      
 366 
     | 
    
         
            +
                    [:octet, 1],
         
     | 
| 
      
 367 
     | 
    
         
            +
                    [:shortstr, 'abc'],
         
     | 
| 
      
 368 
     | 
    
         
            +
                    [:bit, true],
         
     | 
| 
      
 369 
     | 
    
         
            +
                    [:bit, false],
         
     | 
| 
      
 370 
     | 
    
         
            +
                    [:shortstr, nil],
         
     | 
| 
      
 371 
     | 
    
         
            +
                    [:timestamp, nil],
         
     | 
| 
      
 372 
     | 
    
         
            +
                    [:table, { :a => 'hash' }],
         
     | 
| 
      
 373 
     | 
    
         
            +
                  ]*5).sort_by{rand}
         
     | 
| 
      
 374 
     | 
    
         
            +
                  
         
     | 
| 
      
 375 
     | 
    
         
            +
                  @buf.write(:properties, properties)
         
     | 
| 
      
 376 
     | 
    
         
            +
                  @buf.rewind
         
     | 
| 
      
 377 
     | 
    
         
            +
                  @buf.read(:properties, *properties.map{|type,_| type }).should == properties.map{|_,value| value }
         
     | 
| 
      
 378 
     | 
    
         
            +
                  @buf.should.be.empty
         
     | 
| 
      
 379 
     | 
    
         
            +
                end
         
     | 
| 
      
 380 
     | 
    
         
            +
             
     | 
| 
      
 381 
     | 
    
         
            +
                should 'do transactional reads with #extract' do
         
     | 
| 
      
 382 
     | 
    
         
            +
                  @buf.write :octet, 8
         
     | 
| 
      
 383 
     | 
    
         
            +
                  orig = @buf.to_s
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
                  @buf.rewind
         
     | 
| 
      
 386 
     | 
    
         
            +
                  @buf.extract do |b|
         
     | 
| 
      
 387 
     | 
    
         
            +
                    b.read :octet
         
     | 
| 
      
 388 
     | 
    
         
            +
                    b.read :short
         
     | 
| 
      
 389 
     | 
    
         
            +
                  end
         
     | 
| 
      
 390 
     | 
    
         
            +
             
     | 
| 
      
 391 
     | 
    
         
            +
                  @buf.pos.should == 0
         
     | 
| 
      
 392 
     | 
    
         
            +
                  @buf.data.should == orig
         
     | 
| 
      
 393 
     | 
    
         
            +
                end
         
     | 
| 
      
 394 
     | 
    
         
            +
              end
         
     | 
| 
      
 395 
     | 
    
         
            +
            end
         
     |