module RedisClient::RESP3

Constants

DUMP_TYPES
EOL
EOL_SIZE
Error
INTEGER_RANGE
PARSER_TYPES
SyntaxError
UnknownType

Public Instance Methods

dump(command, buffer = nil) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 36
def dump(command, buffer = nil)
  buffer ||= new_buffer
  command = command.flat_map do |element|
    case element
    when Hash
      element.flatten
    else
      element
    end
  end
  dump_array(command, buffer)
end
dump_any(object, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 57
def dump_any(object, buffer)
  method = DUMP_TYPES.fetch(object.class) do |unexpected_class|
    if superclass = DUMP_TYPES.keys.find { |t| t > unexpected_class }
      DUMP_TYPES[superclass]
    else
      raise TypeError, "Unsupported command argument type: #{unexpected_class}"
    end
  end
  send(method, object, buffer)
end
dump_array(array, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 68
def dump_array(array, buffer)
  buffer << '*' << array.size.to_s << EOL
  array.each do |item|
    dump_any(item, buffer)
  end
  buffer
end
dump_hash(hash, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 84
def dump_hash(hash, buffer)
  buffer << '%' << hash.size.to_s << EOL
  hash.each_pair do |key, value|
    dump_any(key, buffer)
    dump_any(value, buffer)
  end
  buffer
end
dump_numeric(numeric, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 93
def dump_numeric(numeric, buffer)
  dump_string(numeric.to_s, buffer)
end
dump_set(set, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 76
def dump_set(set, buffer)
  buffer << '~' << set.size.to_s << EOL
  set.each do |item|
    dump_any(item, buffer)
  end
  buffer
end
dump_string(string, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 97
def dump_string(string, buffer)
  string = string.b unless string.ascii_only?
  buffer << '$' << string.bytesize.to_s << EOL << string << EOL
end
dump_symbol(symbol, buffer) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 103
def dump_symbol(symbol, buffer)
  dump_string(symbol.name, buffer)
end
load(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 49
def load(io)
  parse(io)
end
new_buffer() click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 53
def new_buffer
  String.new(encoding: Encoding::BINARY, capacity: 127)
end
parse(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 112
def parse(io)
  type = io.getbyte
  if type == 35 # '#'.ord
    parse_boolean(io)
  elsif type == 36 # '$'.ord
    parse_blob(io)
  elsif type == 43 # '+'.ord
    parse_string(io)
  elsif type == 61 # '='.ord
    parse_verbatim_string(io)
  elsif type == 45 # '-'.ord
    parse_error(io)
  elsif type == 58 # ':'.ord
    parse_integer(io)
  elsif type == 40 # '('.ord
    parse_integer(io)
  elsif type == 44 # ','.ord
    parse_double(io)
  elsif type == 95 # '_'.ord
    parse_null(io)
  elsif type == 42 # '*'.ord
    parse_array(io)
  elsif type == 37 # '%'.ord
    parse_map(io)
  elsif type == 126 # '~'.ord
    parse_set(io)
  elsif type == 62 # '>'.ord
    parse_array(io)
  else
    raise UnknownType, "Unknown sigil type: #{type.chr.inspect}"
  end
end
parse_array(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 166
def parse_array(io)
  parse_sequence(io, io.gets_integer)
end
parse_blob(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 218
def parse_blob(io)
  bytesize = io.gets_integer
  return if bytesize < 0 # RESP2 nil type

  str = io.read_chomp(bytesize)
  str.force_encoding(Encoding::BINARY) unless str.valid_encoding?
  str
end
parse_boolean(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 155
def parse_boolean(io)
  case value = io.gets_chomp
  when "t"
    true
  when "f"
    false
  else
    raise SyntaxError, "Expected `t` or `f` after `#`, got: #{value}"
  end
end
parse_double(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 200
def parse_double(io)
  case value = io.gets_chomp
  when "nan"
    Float::NAN
  when "inf"
    Float::INFINITY
  when "-inf"
    -Float::INFINITY
  else
    Float(value)
  end
end
parse_error(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 151
def parse_error(io)
  CommandError.parse(parse_string(io))
end
parse_integer(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 196
def parse_integer(io)
  Integer(io.gets_chomp)
end
parse_map(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 174
def parse_map(io)
  hash = {}
  io.gets_integer.times do
    hash[parse(io).freeze] = parse(io)
  end
  hash
end
parse_null(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 213
def parse_null(io)
  io.skip(EOL_SIZE)
  nil
end
parse_push(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 182
def parse_push(io)
  parse_array(io)
end
parse_sequence(io, size) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 186
def parse_sequence(io, size)
  return if size < 0 # RESP2 nil

  array = Array.new(size)
  size.times do |index|
    array[index] = parse(io)
  end
  array
end
parse_set(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 170
def parse_set(io)
  parse_sequence(io, io.gets_integer)
end
parse_string(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 145
def parse_string(io)
  str = io.gets_chomp
  str.force_encoding(Encoding::BINARY) unless str.valid_encoding?
  str.freeze
end
parse_verbatim_string(io) click to toggle source
# File lib/redis_client/ruby_connection/resp3.rb, line 227
def parse_verbatim_string(io)
  blob = parse_blob(io)
  blob.byteslice(4..-1)
end