Class: Tracks::Input

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

Overview

Tracks::Input is used to defer reading of the input stream. It is used internally to Tracks, and should not need to be created outside of Tracks.

Tracks::Input is not rewindable, so will always come wrapped by a Rack::RewindableInput. The #read method conforms to the Rack input spec for #read.

On initialisation the Tracks::Input instance is given an object which it will use to notify it’s creator when input is required. This will be done by calling the #call method on the passed object. This call method should block until after a chunk of input has been fed to the Tracks::Input instance’s #recieve_chunk method.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(reader) ⇒ Input

:call-seq: Input.new(reader) -> input

Create a new Input instance.



93
94
95
96
# File 'lib/tracks.rb', line 93

def initialize(reader)
  @reader = reader
  reset
end

Instance Attribute Details

#finishedObject

set true when the end of the stream has been read into the internal buffer



87
88
89
# File 'lib/tracks.rb', line 87

def finished
  @finished
end

Instance Method Details

#first_read(&block) ⇒ Object

:call-seq: input.first_read { block } -> block

Setup a callback to be executed on when #read is first called. Only one callback can be set, with subsequent calls to this method overriding the previous. Used internally to Tracks for automatic 100-continue support.



145
146
147
# File 'lib/tracks.rb', line 145

def first_read(&block)
  @on_initial_read = block
end

#read(length = nil, output = "") ⇒ Object

:call-seq: input.read([length[, buffer]])

Read at most length bytes from the input stream.

Conforms to the Rack spec for the input stream’s #read method:

If given, length must be an non-negative Integer (>= 0) or nil, and buffer must be a String and may not be nil. If length is given and not nil, then this method reads at most length bytes from the input stream. If length is not given or nil, then this method reads all data until EOF. When EOF is reached, this method returns nil if length is given and not nil, or “” if length is not given or is nil. If buffer is given, then the read data will be placed into buffer instead of a newly created String object.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/tracks.rb', line 113

def read(length=nil, output="")
  @on_initial_read.call if @on_initial_read && !@started
  @started = true
  
  if length && (@buffer || fill_buffer)
    fill_buffer until @buffer.length >= length || @finished
    output.replace(@buffer.slice!(0, length))
    @buffer = nil if @buffer.empty?
  elsif length
    output = nil
  elsif !@finished
    fill_buffer until @finished
    output.replace(@buffer || "")
    @buffer = nil
  end
  output
end

#recieve_chunk(chunk) ⇒ Object

:call-seq: input.recieve_chunk(string) -> string

Append string to the internal buffer.



135
136
137
# File 'lib/tracks.rb', line 135

def recieve_chunk(chunk)
  if @buffer then @buffer << chunk else @buffer = chunk.dup end
end

#resetObject

:call-seq: input.reset -> nil

Reset input, allowing it to be reused.



153
154
155
156
157
# File 'lib/tracks.rb', line 153

def reset
  @started = false
  @finished = false
  @buffer = nil
end