Class: Hatetepe::Body
- Inherits:
-
Object
- Object
- Hatetepe::Body
- Includes:
- EM::Deferrable
- Defined in:
- lib/hatetepe/body.rb
Overview
Thin wrapper around StringIO for asynchronous body processing.
Instance Attribute Summary collapse
-
#io ⇒ Object
readonly
The wrapped StringIO.
-
#source ⇒ Object
The origin Client or Server connection.
Instance Method Summary collapse
-
#close_write ⇒ undefined
Forwards to StringIO#close_write.
-
#closed_write? ⇒ Boolean
Forwards to StringIO#closed_write?.
-
#each {|String| ... } ⇒ Enumerator, self
Yields incoming body data.
-
#empty? ⇒ Boolean
Returns true if the underlying StringIO is empty, false otherwise.
-
#gets ⇒ String?
Forwards to StringIO#gets.
-
#initialize(data = "") ⇒ Body
constructor
Create a new Body instance.
-
#length ⇒ Fixnum
Forwards to StringIO#length.
-
#pos ⇒ Fixnum
Forwards to StringIO#pos.
-
#read(*args) ⇒ nil, String
Forwards to StringIO#read.
-
#rewind ⇒ undefined
Forwards to StringIO#rewind.
-
#rewind! ⇒ Object
Rewinds underlying IO without blocking.
-
#sync ⇒ undefined
Blocks until the Body is write-closed.
-
#write(data) ⇒ Fixnum
Forwards to StringIO#write.
Constructor Details
#initialize(data = "") ⇒ Body
Create a new Body instance.
20 21 22 23 |
# File 'lib/hatetepe/body.rb', line 20 def initialize(data = "") @receivers = [] @io = StringIO.new(data) end |
Instance Attribute Details
#io ⇒ Object (readonly)
The wrapped StringIO.
11 12 13 |
# File 'lib/hatetepe/body.rb', line 11 def io @io end |
#source ⇒ Object
The origin Client or Server connection.
14 15 16 |
# File 'lib/hatetepe/body.rb', line 14 def source @source end |
Instance Method Details
#close_write ⇒ undefined
Forwards to StringIO#close_write.
Write-closes the body and succeeds, thus releasing all blocking method calls like #length, #each, #read and #get.
92 93 94 95 |
# File 'lib/hatetepe/body.rb', line 92 def close_write io.close_write succeed end |
#closed_write? ⇒ Boolean
Forwards to StringIO#closed_write?.
Returns true if the body is write-closed, false otherwise.
103 104 105 |
# File 'lib/hatetepe/body.rb', line 103 def closed_write? io.closed_write? end |
#each {|String| ... } ⇒ Enumerator, self
Yields incoming body data.
Immediately yields all data that has already arrived. Blocks until the Body is write-closed and yields for each call to #write until then.
115 116 117 118 119 120 121 122 123 |
# File 'lib/hatetepe/body.rb', line 115 def each(&block) return to_enum(__method__) unless block @receivers << block block.call io.string.dup unless io.string.empty? sync self end |
#empty? ⇒ Boolean
Returns true if the underlying StringIO is empty, false otherwise.
52 53 54 |
# File 'lib/hatetepe/body.rb', line 52 def empty? length == 0 end |
#gets ⇒ String?
Forwards to StringIO#gets.
Reads one line from the IO. Returns the line or nil
if EOF has been reached.
159 160 161 162 |
# File 'lib/hatetepe/body.rb', line 159 def gets sync io.gets end |
#length ⇒ Fixnum
Forwards to StringIO#length.
Blocks until the Body is write-closed. Returns the current length of the underlying StringIO’s content.
43 44 45 46 |
# File 'lib/hatetepe/body.rb', line 43 def length sync io.length end |
#pos ⇒ Fixnum
Forwards to StringIO#pos.
Returns the underlying StringIO’s current pointer position.
62 63 64 |
# File 'lib/hatetepe/body.rb', line 62 def pos io.pos end |
#read(*args) ⇒ nil, String
Forwards to StringIO#read.
From the Rack Spec: If given, length
must be a 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.
145 146 147 148 |
# File 'lib/hatetepe/body.rb', line 145 def read(*args) sync io.read *args end |
#rewind ⇒ undefined
Forwards to StringIO#rewind.
Moves the underlying StringIO’s pointer back to the beginnung.
71 72 73 74 |
# File 'lib/hatetepe/body.rb', line 71 def rewind sync rewind! end |
#rewind! ⇒ Object
Rewinds underlying IO without blocking
TODO this is a hack. the whole blocking/rewinding stuff needs to be
more though out.
82 83 84 |
# File 'lib/hatetepe/body.rb', line 82 def rewind! io.rewind end |
#sync ⇒ undefined
Blocks until the Body is write-closed.
Use this if you want to wait until all of the body has arrived before continuing. It will resume the originating connection if it’s paused.
31 32 33 34 |
# File 'lib/hatetepe/body.rb', line 31 def sync source.resume if source && source.paused? EM::Synchrony.sync self end |
#write(data) ⇒ Fixnum
Forwards to StringIO#write.
Appends the given String to the underlying StringIO annd returns the number of bytes written.
174 175 176 177 178 179 180 |
# File 'lib/hatetepe/body.rb', line 174 def write(data) ret = io.write data @receivers.each do |r| Fiber.new { r.call data }.resume end ret end |