class Repobrowse::LimitRd

Copyright (C) 2017-2018 all contributors <repobrowse-public@80x24.org> License: AGPL-3.0+ <www.gnu.org/licenses/agpl-3.0.txt>

Public Class Methods

new(rd, size, buf, &blk) click to toggle source
# File lib/repobrowse/limit_rd.rb, line 6
def initialize(rd, size, buf, &blk)
  @rd = rd # git cat-file --batch output
  @left = size == 0 ? nil : size
  @buf = buf
  @on_close = blk
  @peek = nil
end

Public Instance Methods

close() click to toggle source

called by Rack server in ensure

# File lib/repobrowse/limit_rd.rb, line 15
def close
  @on_close&.call(self) # allows our @rd to be reused
  @buf&.clear
  @peek&.clear
  @on_close = nil
end
drain() click to toggle source

we must drain the buffer if the reader aborted prematurely

# File lib/repobrowse/limit_rd.rb, line 77
def drain
  n = @left or return
  max = 16384
  while n > 0
    len = n > max ? max : n
    @rd.read(len, @buf) and n -= @buf.bytesize
  end
end
each() { |peek| ... } click to toggle source

called by Rack server

# File lib/repobrowse/limit_rd.rb, line 28
def each
  peek, @peek = @peek, nil
  yield peek if peek
  while read(16384, @buf)
    yield @buf
  end
end
gets(sep = $/, limit = nil, chomp: false) click to toggle source

non-Rack response body interface

# File lib/repobrowse/limit_rd.rb, line 52
def gets(sep = $/, limit = nil, chomp: false)
  if Integer === sep && limit.nil?
    limit = sep
    sep = $/
  end
  raise RuntimeError, 'not #read is compatible with #peek' if @peek
  return if @left.nil?
  return '' if limit == 0
  limit = @left if limit.nil? || limit > @left
  if limit == 0
    @left = nil
    return nil
  end
  buf = @rd.gets(sep, limit)
  if buf
    @left -= buf.bytesize
    @left = nil if @left == 0

    # we must chomp ourselves for accounting @left
    buf.chomp!(sep) if chomp
  end
  buf
end
peek(len = 8000) click to toggle source

used to determine if a file is binary or text

# File lib/repobrowse/limit_rd.rb, line 23
def peek(len = 8000) # 8000 bytes is the same size used by git
  @peek = read(len, @buf)
end
read(len = nil, buf = nil) click to toggle source

non-Rack response body interface

# File lib/repobrowse/limit_rd.rb, line 37
def read(len = nil, buf = nil)
  raise RuntimeError, 'not #read is compatible with #peek' if @peek
  if @left
    len = @left if len.nil? || len > @left
    ret = @rd.read(len, buf)
    @left -= ret.bytesize if ret
    @left = nil if @left == 0
    ret
  else
    buf&.clear
    len ? nil : ''
  end
end