class Net::BufferedIO

:nodoc: internal use only

def LOG(msg)

def LOG(msg)
  return unless @debug_output
  @debug_output << msg + "\n"
end

def LOG_off

def LOG_off
  @save_debug_out = @debug_output
  @debug_output = nil
end

def LOG_on

def LOG_on
  @debug_output = @save_debug_out
end

def close

def close
  @io.close
end

def closed?

def closed?
  @io.closed?
end

def eof?

def eof?
  @io.eof?
end

def initialize(io, read_timeout: 60, write_timeout: 60, continue_timeout: nil, debug_output: nil)

:nodoc: internal use only
def initialize(io, read_timeout: 60, write_timeout: 60, continue_timeout: nil, debug_output: nil)
  @io = io
  @read_timeout = read_timeout
  @write_timeout = write_timeout
  @continue_timeout = continue_timeout
  @debug_output = debug_output
  @rbuf = ''.b
end

def inspect

def inspect
  "#<#{self.class} io=#{@io}>"
end

def rbuf_consume(len)

def rbuf_consume(len)
  if len == @rbuf.size
    s = @rbuf
    @rbuf = ''.b
  else
    s = @rbuf.slice!(0, len)
  end
  @debug_output << %Q[-> #{s.dump}\n] if @debug_output
  s
end

def rbuf_fill

def rbuf_fill
  tmp = @rbuf.empty? ? @rbuf : nil
  case rv = @io.read_nonblock(BUFSIZE, tmp, exception: false)
  when String
    return if rv.equal?(tmp)
    @rbuf << rv
    rv.clear
    return
  when :wait_readable
    (io = @io.to_io).wait_readable(@read_timeout) or raise Net::ReadTimeout.new(io)
    # continue looping
  when :wait_writable
    # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable.
    # http://www.openssl.org/support/faq.html#PROG10
    (io = @io.to_io).wait_writable(@read_timeout) or raise Net::ReadTimeout.new(io)
    # continue looping
  when nil
    raise EOFError, 'end of file reached'
  end while true
end

def read(len, dest = ''.b, ignore_eof = false)

def read(len, dest = ''.b, ignore_eof = false)
  LOG "reading #{len} bytes..."
  read_bytes = 0
  begin
    while read_bytes + @rbuf.size < len
      s = rbuf_consume(@rbuf.size)
      read_bytes += s.size
      dest << s
      rbuf_fill
    end
    s = rbuf_consume(len - read_bytes)
    read_bytes += s.size
    dest << s
  rescue EOFError
    raise unless ignore_eof
  end
  LOG "read #{read_bytes} bytes"
  dest
end

def read_all(dest = ''.b)

def read_all(dest = ''.b)
  LOG 'reading all...'
  read_bytes = 0
  begin
    while true
      s = rbuf_consume(@rbuf.size)
      read_bytes += s.size
      dest << s
      rbuf_fill
    end
  rescue EOFError
    ;
  end
  LOG "read #{read_bytes} bytes"
  dest
end

def readline

def readline
  readuntil("\n").chop
end

def readuntil(terminator, ignore_eof = false)

def readuntil(terminator, ignore_eof = false)
  begin
    until idx = @rbuf.index(terminator)
      rbuf_fill
    end
    return rbuf_consume(idx + terminator.size)
  rescue EOFError
    raise unless ignore_eof
    return rbuf_consume(@rbuf.size)
  end
end

def write(*strs)

def write(*strs)
  writing {
    write0(*strs)
  }
end

def write0(*strs)

def write0(*strs)
  @debug_output << strs.map(&:dump).join if @debug_output
  orig_written_bytes = @written_bytes
  strs.each_with_index do |str, i|
    need_retry = true
    case len = @io.write_nonblock(str, exception: false)
    when Integer
      @written_bytes += len
      len -= str.bytesize
      if len == 0
        if strs.size == i+1
          return @written_bytes - orig_written_bytes
        else
          need_retry = false
          # next string
        end
      elsif len < 0
        str = str.byteslice(len, -len)
      else # len > 0
        need_retry = false
        # next string
      end
      # continue looping
    when :wait_writable
      (io = @io.to_io).wait_writable(@write_timeout) or raise Net::WriteTimeout.new(io)
      # continue looping
    end while need_retry
  end
end

def writeline(str)

def writeline(str)
  writing {
    write0 str + "\r\n"
  }
end

def writing

def writing
  @written_bytes = 0
  @debug_output << '<- ' if @debug_output
  yield
  @debug_output << "\n" if @debug_output
  bytes = @written_bytes
  @written_bytes = nil
  bytes
end