<commit_before>require "socket"

# A connection to a Redis instance.

# :nodoc:
class Redis::Connection
  def initialize(host, port, unixsocket)
    if unixsocket
      @socket = UNIXSocket.new(unixsocket)
    else
      @socket = TCPSocket.new(host, port)
    end
    @socket.sync = false
    @connected = true
  end

  def finalize
    close
  end

  def close
    if @connected
      @socket.close
      @connected = false
    end
  end

  def send(request : Request)
    queue(request)
    flush
  end

  def queue(request : Request)
    marshal(request, @socket)
  end

  def flush
    @socket.flush
  end

  def marshal(arg : Int, io)
    io << ":" << arg << "\r\n"
  end

  def marshal(arg : String, io)
    io << "$" << arg.bytesize << "\r\n" << arg << "\r\n"
  end

  def marshal(arg : Array(RedisValue), io)
    io << "*" << arg.size << "\r\n"
    arg.each do |element|
      marshal(element, io)
    end
  end

  def marshal(arg : Nil, io)
    io << "$-1\r\n"
  end

  # Receives n responses with the expected content "QUEUED".
  # This method exists to prevent many small read calls.
  #
  def receive_queued_responses(n)
    if n == 0
      return
    end
    bytes_per_queued_responses = "+QUEUED\r\n".bytesize
    nbytes = n * bytes_per_queued_responses
    @socket.skip(nbytes)
  end

  def receive
    type = @socket.read_char
    line = receive_line

    case type
    when '-'
      # Error
      raise Redis::Error.new(line)
    when ':'
      # Integer
      line.to_i64
    when '$'
      # Bulk string
      length = line.to_i

      # The "Null bulk string" aka nil
      return nil if length == -1

      bulk_string = String.new(length) do |buffer|
        @socket.read_fully(Slice.new(buffer, length))
        {length, 0}
      end
      # Ignore CR/LF
      @socket.skip(2)
      bulk_string
    when '+'
      # Simple string
      line
    when '*'
      # Array
      length = line.to_i
      result = [] of RedisValue
      length.times do
        result << receive
      end
      result
    when nil
      raise Redis::Error.new("Received nil type string")
    else
      raise Redis::Error.new("Cannot parse response with type #{type}: #{receive_line.inspect}")
    end
  end

  def receive_line
    line = @socket.gets
    unless line
      raise Redis::Error.new("Disconnected")
    end
    line.byte_slice(0, line.bytesize - 2)
  end
end<commit_msg>Fix error message for issue #8<commit_after>require "socket"

# A connection to a Redis instance.

# :nodoc:
class Redis::Connection
  def initialize(host, port, unixsocket)
    if unixsocket
      @socket = UNIXSocket.new(unixsocket)
    else
      @socket = TCPSocket.new(host, port)
    end
    @socket.sync = false
    @connected = true
  end

  def finalize
    close
  end

  def close
    if @connected
      @socket.close
      @connected = false
    end
  end

  def send(request : Request)
    queue(request)
    flush
  end

  def queue(request : Request)
    marshal(request, @socket)
  end

  def flush
    @socket.flush
  end

  def marshal(arg : Int, io)
    io << ":" << arg << "\r\n"
  end

  def marshal(arg : String, io)
    io << "$" << arg.bytesize << "\r\n" << arg << "\r\n"
  end

  def marshal(arg : Array(RedisValue), io)
    io << "*" << arg.size << "\r\n"
    arg.each do |element|
      marshal(element, io)
    end
  end

  def marshal(arg : Nil, io)
    io << "$-1\r\n"
  end

  # Receives n responses with the expected content "QUEUED".
  # This method exists to prevent many small read calls.
  #
  def receive_queued_responses(n)
    if n == 0
      return
    end
    bytes_per_queued_responses = "+QUEUED\r\n".bytesize
    nbytes = n * bytes_per_queued_responses
    @socket.skip(nbytes)
  end

  def receive
    type = @socket.read_char
    line = receive_line

    case type
    when '-'
      # Error
      raise Redis::Error.new(line)
    when ':'
      # Integer
      line.to_i64
    when '$'
      # Bulk string
      length = line.to_i

      # The "Null bulk string" aka nil
      return nil if length == -1

      bulk_string = String.new(length) do |buffer|
                      @socket.read_fully(Slice.new(buffer, length))
                      {length, 0}
                    end
      # Ignore CR/LF
      @socket.skip(2)
      bulk_string
    when '+'
      # Simple string
      line
    when '*'
      # Array
      length = line.to_i
      result = [] of RedisValue
      length.times do
        result << receive
      end
      result
    when nil
      raise Redis::Error.new("Received nil type string")
    else
      raise Redis::Error.new("Cannot parse response with type #{type}: #{line.inspect}")
    end
  end

  def receive_line
    line = @socket.gets
    unless line
      raise Redis::Error.new("Disconnected")
    end
    line.byte_slice(0, line.bytesize - 2)
  end
end
{'fraction_non_alphanumeric': 0.10922279792746115, 'fraction_numerical': 0.003937823834196891, 'mean_word_length': 2.0935897435897437, 'pattern_counts': {'":': 2, '<': 55, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1324169', 'n_tokens_mistral': 1651, 'n_tokens_neox': 1604, 'n_words': 446}