Jump To …

FixedLengthByteIterable.coffee

ByteIterableBase =
  (require '../../database/impl/iterate/ByteIterableBase.coffee').
  ByteIterableBase
RandomAccessByteIterable =
  (require '../RandomAccessByteIterable.coffee').RandomAccessByteIterable
ByteIterator =
  (require '../../database/ByteIterator.coffee').ByteIterator
ExodusError = (require '../../errors/ExodusError.coffee').ExodusError

This class allows working with fixed parts of other iterables.

class FixedLengthByteIterable extends ByteIterableBase

@private

  source: undefined

@private

  offset: undefined

Constructor.

@param source the base ByteIterable. @param offset the offset inside iterable. @param length the length of data of the source to be used.

  @create$ByteIterable$int$int: (source, offset, length, o) ->
    if length < 0
      throw new ExodusError("ByteIterable length can't be less than zero")
    if !o? then o = new FixedLengthByteIterable
    o.source = source
    o.offset = offset
    o.length = length
    return o

Constructor.

@param source the base ByteIterable. @param length the length of data of the source to be used.

  @create$ByteIterable$int: (source, length, o) ->
    return FixedLengthByteIterable.create$ByteIterable$int$int source, 0,
            length, o

Compare this iterable to another.

@param right another iterable. @return always emits 'compare' event with number (see ByteIterableUtil.compare$ByteIterable$ByteIterable).

  compareTo$ByteIterable$emit: (right) ->
    onCompare = (res) =>
      @emit 'compare', res
    if @source instanceof RandomAccessByteIterable
      @source.once 'compare', (res) =>
        onCompare res
      res = @source.compare$int$int$ByteIterable$emit 0, @length, right
      if res?
        @source.removeAllListeners 'compare'
        onCompare res
    else
      res = @source.compareTo$ByteIterable$emit right
      onCompare res

  getLength: () ->
    return @length

@protected

  getIterator: () ->
    if @length == 0
      return ByteIterableBase.EMPTY_ITERATOR
    bi = @source.iterator()
    bi.skip$int @offset
    res = new ByteIterator()
    res.i = @length
    res.hasNext$emit = () ->
      bi.once 'hasNext', (hasNext) =>
        @emit 'hasNext',  @i > 0 && hasNext
      hasNext = bi.hasNext$emit()
      if hasNext?
        bi.removeAllListeners 'hasNext'
        return @i > 0 && hasNext
      else
        return undefined
    res.next$emit = () ->
      @i -= 1
      bi.once 'next', (next) =>
        @emit 'next', next
      next = bi.next$emit()
      if next?
        bi.removeAllListeners 'next'
        return next
      else
        return undefined
    res.skip$int = (length) ->
      result = bi.skip Math.min @length, @i
      @i -= result
      return result
    return res

exports.FixedLengthByteIterable = FixedLengthByteIterable