class FormatParser::ReadLimiter
Is used to limit the number of reads/seeks parsers can perform
Constants
- NO_LIMIT
Attributes
Public Class Methods
Creates a ReadLimiter
wrapper around the given IO object and sets the limits on the number of reads/writes
@param io[#seek, pos
, size
, read
] the IO object to wrap @param max_bytes[Integer, nil] how many bytes can we read from this before an exception is raised @param max_reads[Integer, nil] how many read() calls can we perform on this before an exception is raised @param max_seeks[Integer, nil] how many seek() calls can we perform on this before an exception is raised
# File lib/read_limiter.rb, line 17 def initialize(io, max_bytes: NO_LIMIT, max_reads: NO_LIMIT, max_seeks: NO_LIMIT) @max_bytes = max_bytes @max_reads = max_reads @max_seeks = max_seeks @io = io @seeks = 0 @reads = 0 @bytes = 0 end
Public Instance Methods
Returns the current position/offset within the IO
@return Integer
# File lib/read_limiter.rb, line 38 def pos @io.pos end
Returns at most `n_bytes` of data from the IO or less if less data was available before the EOF was hit
@param n_bytes @return [String, nil] the content read from the IO or `nil` if no data was available
# File lib/read_limiter.rb, line 59 def read(n_bytes) @bytes += n_bytes @reads += 1 if @max_bytes && @bytes > @max_bytes raise BudgetExceeded, 'Read bytes budget (%d) exceeded' % @max_bytes end if @max_reads && @reads > @max_reads raise BudgetExceeded, 'Number of read() calls exceeded (%d max)' % @max_reads end @io.read(n_bytes) end
Resets all the recorded call counters so that the object can be reused for the next parser, which will have it's own limits @return void
# File lib/read_limiter.rb, line 88 def reset_limits! @seeks = 0 @reads = 0 @bytes = 0 end
Seeks the IO to the given absolute offset from the start of the file/resource
@param to offset in the IO @return Integer
# File lib/read_limiter.rb, line 46 def seek(to) @seeks += 1 if @max_seeks && @seeks > @max_seeks raise BudgetExceeded, 'Seek budget exceeded (%d seeks performed)' % @max_seeks end @io.seek(to) end
Sends the metrics about the state of this ReadLimiter
to a Measurometer
@param prefix the prefix to set. For example, with prefix “TIFF” the metrics will be called
`format_parser.TIFF.read_limiter.num_seeks` and so forth
@return void
# File lib/read_limiter.rb, line 79 def send_metrics(prefix) Measurometer.add_distribution_value('format_parser.%s.read_limiter.num_seeks' % prefix, @seeks) Measurometer.add_distribution_value('format_parser.%s.read_limiter.num_reads' % prefix, @reads) Measurometer.add_distribution_value('format_parser.%s.read_limiter.read_bytes' % prefix, @bytes) end
Returns the size of the resource contained in the IO
@return Integer
# File lib/read_limiter.rb, line 31 def size @io.size end