module BinData::IO::Common::UnSeekableStream

def num_bytes_remaining

The number of bytes remaining in the input stream.
def num_bytes_remaining
  raise IOError, "stream is unseekable"
end

def offset_raw

def offset_raw
  @offset
end

def read_raw(n)

def read_raw(n)
  data = @raw_io.read(n)
  @offset += data.size if data
  data
end

def read_raw_with_readahead(n)

def read_raw_with_readahead(n)
  data = ""
  if @read_data.length > 0 and not @in_readahead
    bytes_to_consume = [n, @read_data.length].min
    data << @read_data.slice!(0, bytes_to_consume)
    n -= bytes_to_consume
    if @read_data.length == 0
      class << self
        alias_method :read_raw, :read_raw_without_readahead
      end
    end
  end
  raw_data = @raw_io.read(n)
  data << raw_data if raw_data
  if @in_readahead
    @read_data << data
  end
  @offset += data.size
  data
end

def seek_raw(n)

def seek_raw(n)
  raise IOError, "stream is unseekable" if n < 0
  # NOTE: how do we seek on a writable stream?
  # skip over data in 8k blocks
  while n > 0
    bytes_to_read = [n, 8192].min
    read_raw(bytes_to_read)
    n -= bytes_to_read
  end
end

def stream_init

def stream_init
  @offset = 0
end

def with_readahead(&block)

method completes.
All io calls in +block+ are rolled back after this
def with_readahead(&block)
  mark = @offset
  @read_data = ""
  @in_readahead = true
  class << self
    alias_method :read_raw_without_readahead, :read_raw
    alias_method :read_raw, :read_raw_with_readahead
  end
  begin
    block.call
  ensure
    @offset = mark
    @in_readahead = false
  end
end

def write_raw(data)

def write_raw(data)
  @offset += data.size
  @raw_io.write(data)
end