module Sinatra::Streaming::Stream

def self.extended(obj)

def self.extended(obj)
  obj.closed = false
  obj.lineno = 0
  obj.pos = 0
  obj.callback { obj.closed = true }
  obj.errback  { obj.closed = true }
end

def <<(data)

def <<(data)
  raise IOError, 'not opened for writing' if closed?
  @transformer ||= nil
  data = data.to_s
  data = @transformer[data] if @transformer
  @pos += data.bytesize
  super(data)
end

def close_read

def close_read
  raise IOError, 'closing non-duplex IO for reading'
end

def closed_read?

def closed_read?
  true
end

def closed_write?

def closed_write?
  closed?
end

def dummy(*) end

def dummy(*) end

def each

def each
  # that way body.each.map { ... } works
  return self unless block_given?
  super
end

def enum_not_open_for_reading(*)

def enum_not_open_for_reading(*)
  not_open_for_reading if block_given?
  enum_for(:not_open_for_reading)
end

def external_encoding

def external_encoding
  Encoding.find settings.default_encoding
rescue NameError
  settings.default_encoding
end

def map(&block)

def map(&block)
  # dup would not copy the mixin
  clone.map!(&block)
end

def map!(&block)

def map!(&block)
  @transformer ||= nil
  if @transformer
    inner = @transformer
    outer = block
    block = proc { |value| outer[inner[value]] }
  end
  @transformer = block
  self
end

def not_open_for_reading(*)

def not_open_for_reading(*)
  raise IOError, 'not opened for reading'
end

def print(*args)

def print(*args)
  args.each { |arg| self << arg }
  nil
end

def printf(format, *args)

def printf(format, *args)
  print(format.to_s % args)
end

def putc(c)

def putc(c)
  print c.chr
end

def puts(*args)

def puts(*args)
  args.each { |arg| self << "#{arg}\n" }
  nil
end

def rewind

def rewind
  @pos = @lineno = 0
end

def seek(*)

def seek(*)
  0
end

def settings

def settings
  app.settings
end

def sync

def sync
  true
end

def tty?

def tty?
  false
end

def write(data)

def write(data)
  self << data
  data.to_s.bytesize
end