class RABX::Message

Constants

VERSION

Attributes

version[R]

Public Class Methods

dump(type, *args) click to toggle source

Dumps a RABX message.

@param [String] type a message type @param [Array] args message contents @return [String] the REBX message

# File lib/rabx/message.rb, line 14
def self.dump(type, *args)
  string = type + Netstring.dump('0')
  if type == 'R'
    string + Netstring.dump(args[0]) + _dump(args[1])
  elsif type == 'S'
    if args.size.zero?
      string
    else
      string + _dump(args[0])
    end
  elsif type == 'E'
    string + Netstring.dump(args[0].to_s) + Netstring.dump(args[1]) + _dump(args[2])
  end
end
load(s) click to toggle source

Loads a RABX message.

@param [String] s a RABX message @return [Message] a parsed message

# File lib/rabx/message.rb, line 33
def self.load(s)
  case s[0]
  when 'R'
    RequestMessage.new(s)
  when 'S'
    SuccessMessage.new(s)
  when 'E'
    ErrorMessage.new(s)
  else
    raise ProtocolError, %(unknown RABX message type "#{s[0]}")
  end
end
new(s) click to toggle source

@param [String] s a RABX message

# File lib/rabx/message.rb, line 49
def initialize(s)
  if s.empty?
    raise ProtocolError, 'string is too short'
  end
  @s = s.dup # string
  @p = 1 # pointer
  @size = @s.size
  @version = getnetstring
  parse
end

Private Class Methods

_dump(args) click to toggle source
# File lib/rabx/message.rb, line 173
def self._dump(args)
  case args
  when nil
    'N'
  when true
    'I' + Netstring.dump('1')
  when false
    'I' + Netstring.dump('0')
  when Integer
    'I' + Netstring.dump(args.to_s)
  when Float
    'R' + Netstring.dump(args.to_s)
  when String
    'T' + Netstring.dump(args)
  when Symbol
    'T' + Netstring.dump(args.to_s)
  when Array
    'L' + Netstring.dump(args.size.to_s) + args.map{|arg| _dump(arg)}.join
  when Hash
    'A' + Netstring.dump(args.size.to_s) + args.map{|k,v| _dump(k) + _dump(v)}.join
  else
    raise InterfaceError, "can't pass #{args.class} over RABX"
  end
end

Public Instance Methods

eof?() click to toggle source

Returns whether the reader has reached the end-of-file.

@return [Boolean] whether the reader has reached the end-of-file

# File lib/rabx/message.rb, line 77
def eof?
  @p == @size
end
getnetstring() click to toggle source

Loads a netstring from the current position in the message.

@return [Netstring,nil] a string, or nil if at end-of-file

# File lib/rabx/message.rb, line 84
def getnetstring
  if eof?
    nil
  else
    string = Netstring.load(@s[@p..-1])
    @p += string.netstring.size
    string
  end
rescue Netstring::Error => e
  raise ProtocolError, "#{e.message} in netstring starting at #{@p}"
end
gets() click to toggle source

Loads a typed netstring from the current position in the message.

@return the contents of the netstring, or nil if at end-of-file

# File lib/rabx/message.rb, line 99
def gets
  if eof?
    nil
  else
    type = @s[@p]
    @p += 1

    if type == 'N' # null
      return nil
    end

    case type
    when 'I' # integer
      value = getnetstring.to_s
      begin
        Integer(value)
      rescue ArgumentError
        raise ProtocolError, %(expected integer, got #{value.inspect} at position #{@p - value.size - 1})
      end
    when 'R' # real
      value = getnetstring.to_s
      begin
        Float(value)
      rescue ArgumentError
        raise ProtocolError, %(expected float, got #{value.inspect} at position #{@p - value.size - 1})
      end
    when 'T', 'B' # text, binary
      getnetstring
    when 'L' # list
      value = getnetstring.to_s
      begin
        size = Integer(value)
      rescue ArgumentError
        raise ProtocolError, %(expected integer, got #{value.inspect} at position #{@p - value.size - 1})
      end
      array = []
      size.times do |n|
        if eof?
          raise ProtocolError, %(expected #{size} items, got #{n} items at position #{@p})
        end
        array << gets
      end
      array
    when 'A' # associative array
      value = getnetstring.to_s
      begin
        size = Integer(value)
      rescue ArgumentError
        raise ProtocolError, %(expected integer, got #{value.inspect} at position #{@p - value.size - 1})
      end
      hash = {}
      size.times do |n|
        if eof?
          raise ProtocolError, %(expected #{size} items, got #{n} items at position #{@p})
        end
        key = gets # test for repeated keys?
        if eof?
          raise ProtocolError, %(expected value, got end-of-file at position #{@p})
        end
        hash[key] = gets
      end
      hash
    else
      raise ProtocolError, %(bad type character "#{type}" at position #{@p})
    end
  end
end
to_s() click to toggle source

Returns the RABX message.

@return [String] the RABX message

# File lib/rabx/message.rb, line 63
def to_s
  @s
end
type() click to toggle source

Returns the message type.

@return [String] the message type

# File lib/rabx/message.rb, line 70
def type
  @s[0]
end

Private Instance Methods

parse() click to toggle source
# File lib/rabx/message.rb, line 169
def parse
  # If not implemented, user can read message using `getnetstring` and `gets`.
end