class Net::IMAP::ResponseReader

def bytes_read = buff.bytesize

def bytes_read          = buff.bytesize

def done? = line_done? && !get_literal_size

def done?               = line_done? && !get_literal_size

def empty? = buff.empty?

def empty?              = buff.empty?

def get_literal_size = /\{(\d+)\}\r\n\z/n =~ buff && $1.to_i

def get_literal_size    = /\{(\d+)\}\r\n\z/n =~ buff && $1.to_i

def initialize(client, sock)

def initialize(client, sock)
  @client, @sock = client, sock
end

def line_done? = buff.end_with?(CRLF)

def line_done?          = buff.end_with?(CRLF)

def max_response_remaining = max_response_size &.- bytes_read

def max_response_remaining = max_response_size &.- bytes_read

def max_response_remaining!

def max_response_remaining!
  return max_response_remaining unless response_too_large?
  raise ResponseTooLargeError.new(
    max_response_size:, bytes_read:, literal_size:,
  )
end

def max_response_size = client.max_response_size

def max_response_size      = client.max_response_size

def min_response_remaining

def min_response_remaining
  empty? ? 3 : done? ? 0 : (literal_size || 0) + 2
end

def min_response_size = bytes_read + min_response_remaining

def min_response_size      = bytes_read + min_response_remaining

def read_limit(limit = nil)

def read_limit(limit = nil)
  [limit, max_response_remaining!].compact.min
end

def read_line

def read_line
  buff << (@sock.gets(CRLF, read_limit) or throw :eof)
  max_response_remaining! unless line_done?
end

def read_literal

def read_literal
  # check before allocating memory for literal
  max_response_remaining!
  literal = String.new(capacity: literal_size)
  buff << (@sock.read(read_limit(literal_size), literal) or throw :eof)
ensure
  @literal_size = nil
end

def read_response_buffer

def read_response_buffer
  @buff = String.new
  catch :eof do
    while true
      read_line
      break unless (@literal_size = get_literal_size)
      read_literal
    end
  end
  buff
ensure
  @buff = nil
end

def response_too_large? = max_response_size &.< min_response_size

def response_too_large?    = max_response_size &.< min_response_size