Class: Prism::CodeUnitsCache

Inherits:
Object
  • Object
show all
Defined in:
lib/prism/parse_result.rb

Overview

A cache that can be used to quickly compute code unit offsets from byte offsets. It purposefully provides only a single #[] method to access the cache in order to minimize surface area.

Note that there are some known issues here that may or may not be addressed in the future:

  • The first is that there are issues when the cache computes values that are not on character boundaries. This can result in subsequent computations being off by one or more code units.

  • The second is that this cache is currently unbounded. In theory we could introduce some kind of LRU cache to limit the number of entries, but this has not yet been implemented.

Instance Method Summary collapse

Constructor Details

#initialize(source, encoding) ⇒ CodeUnitsCache

Initialize a new cache with the given source and encoding.



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/prism/parse_result.rb', line 215

def initialize(source, encoding)
  @source = source
  @counter =
    if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE
      UTF16Counter.new(source, encoding)
    else
      LengthCounter.new(source, encoding)
    end

  @cache = {} #: Hash[Integer, Integer]
  @offsets = [] #: Array[Integer]
end

Instance Method Details

#[](byte_offset) ⇒ Object

Retrieve the code units offset from the given byte offset.



229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/prism/parse_result.rb', line 229

def [](byte_offset)
  @cache[byte_offset] ||=
    if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil?
      @offsets << byte_offset
      @counter.count(0, byte_offset)
    elsif index == 0
      @offsets.unshift(byte_offset)
      @counter.count(0, byte_offset)
    else
      @offsets.insert(index, byte_offset)
      offset = @offsets[index - 1]
      @cache[offset] + @counter.count(offset, byte_offset - offset)
    end
end