class Bones::RPC::Parser

Constants

EXT16
EXT32
EXT8

Attributes

adapter[R]
stream[R]

Public Class Methods

new(stream, adapter) click to toggle source
# File lib/bones/rpc/parser.rb, line 18
def initialize(stream, adapter)
  @stream = stream.force_encoding('BINARY')
  @adapter = Adapter.get(adapter)
end

Public Instance Methods

buffer() click to toggle source
# File lib/bones/rpc/parser.rb, line 14
def buffer
  @buffer ||= Bones::RPC::Parser::Buffer.new(@stream)
end
parser() click to toggle source
# File lib/bones/rpc/parser.rb, line 23
def parser
  @parser ||= @adapter.parser(@stream)
end
read() click to toggle source
# File lib/bones/rpc/parser.rb, line 27
def read
  sync do
    b = buffer.getc
    buffer.ungetc(b)
    if b.nil?
      raise EOFError
    elsif b.start_with?(EXT8)
      pos = buffer.pos
      buffer.skip(1)
      len, = buffer.read(1).unpack('C')
      type, = buffer.read(1).unpack('C')
      check_ext!(type)
      head, = buffer.read(1).unpack('C')
      data = buffer.read(len-1)
      parse_ext!(head, data, pos)
    elsif b.start_with?(EXT16)
      pos = buffer.pos
      buffer.skip(1)
      len, = buffer.read(2).unpack('n')
      type, = buffer.read(1).unpack('C')
      check_ext!(type)
      head, = buffer.read(1).unpack('C')
      data = buffer.read(len-1)
      parse_ext!(head, data, pos)
    elsif b.start_with?(EXT32)
      pos = buffer.pos
      buffer.skip(1)
      len, = buffer.read(4).unpack('N')
      type, = buffer.read(1).unpack('C')
      check_ext!(type)
      head, = buffer.read(1).unpack('C')
      data = buffer.read(len-1)
      parse_ext!(head, data, pos)
    else
      object = parser.read
      buffer.seek(parser.unpacker_pos)
      map_from!(object)
    end
  end
end

Private Instance Methods

check_ext!(type) click to toggle source
# File lib/bones/rpc/parser.rb, line 70
def check_ext!(type)
  raise(Errors::InvalidExtMessage, "bad ext message received of type #{type.inspect} (should be #{0x0D.inspect})") unless valid_ext?(type)
end
map_from!(object) click to toggle source
# File lib/bones/rpc/parser.rb, line 74
def map_from!(object)
  case object
  when Array
    if (3..4).include?(object.size)
      case object.first
      when 0
        Protocol::Request.map_from(object)
      when 1
        Protocol::Response.map_from(object)
      when 2
        Protocol::Notify.map_from(object)
      else
        object
      end
    end
  else
    object
  end
end
parse_ext!(head, data, pos) click to toggle source
# File lib/bones/rpc/parser.rb, line 94
def parse_ext!(head, data, pos)
  message = Protocol.get_by_ext_head(head)
  if message
    message.unpack(data)
  else
    ext_adapter = Adapter.get_by_ext_head(head)
    if ext_adapter == adapter
      buffer.seek(pos)
      object = parser.read
      buffer.seek(parser.unpacker_pos)
      map_from!(object)
    else
      raise(Errors::InvalidExtMessage, "bad ext adapter message received of type #{ext_adapter.inspect} (should be #{adapter.inspect})")
    end
  end
end
sync() { || ... } click to toggle source
# File lib/bones/rpc/parser.rb, line 111
def sync
  buffer.transaction do
    yield
  end
ensure
  parser.unpacker_seek(buffer.pos) if parser.unpacker_pos != buffer.pos
end
valid_ext?(type) click to toggle source
# File lib/bones/rpc/parser.rb, line 119
def valid_ext?(type)
  type == 0x0D
end