Class: RFuzz::PushBackIO
- Inherits:
-
Object
- Object
- RFuzz::PushBackIO
- Defined in:
- lib/rfuzz/pushbackio.rb
Overview
A simple class that using a StringIO object internally to allow for faster and simpler “push back” semantics. It basically lets you read a random amount from a secondary IO object, parse what is needed, and then anything remaining can be quickly pushed back in one chunk for the next read.
Instance Attribute Summary collapse
-
#secondary ⇒ Object
Returns the value of attribute secondary.
Instance Method Summary collapse
- #close ⇒ Object
- #flush ⇒ Object
-
#initialize(secondary) ⇒ PushBackIO
constructor
A new instance of PushBackIO.
- #pop(n) ⇒ Object
- #protect ⇒ Object
-
#push(content) ⇒ Object
Pushes the given string content back onto the stream for the next read to handle.
- #random_death ⇒ Object
-
#read(n, partial = false) ⇒ Object
First does a read from the internal buffer, and then appends anything needed from the secondary IO to complete the request.
- #reset ⇒ Object
- #write(content) ⇒ Object
Constructor Details
#initialize(secondary) ⇒ PushBackIO
Returns a new instance of PushBackIO.
11 12 13 14 15 |
# File 'lib/rfuzz/pushbackio.rb', line 11 def initialize(secondary) @secondary = secondary @buffer = StringIO.new @die_after = rand($io_death_count) if $io_death_count end |
Instance Attribute Details
#secondary ⇒ Object
Returns the value of attribute secondary.
9 10 11 |
# File 'lib/rfuzz/pushbackio.rb', line 9 def secondary @secondary end |
Instance Method Details
#close ⇒ Object
92 93 94 |
# File 'lib/rfuzz/pushbackio.rb', line 92 def close @secondary.close rescue nil end |
#flush ⇒ Object
82 83 84 85 |
# File 'lib/rfuzz/pushbackio.rb', line 82 def flush random_death protect { @secondary.flush } end |
#pop(n) ⇒ Object
33 34 35 36 37 |
# File 'lib/rfuzz/pushbackio.rb', line 33 def pop(n) random_death @buffer.rewind @buffer.read(n) || "" end |
#protect ⇒ Object
96 97 98 99 100 101 102 |
# File 'lib/rfuzz/pushbackio.rb', line 96 def protect if !@secondary.closed? yield else raise HttpClientError.new("Socket closed.") end end |
#push(content) ⇒ Object
Pushes the given string content back onto the stream for the next read to handle.
26 27 28 29 30 31 |
# File 'lib/rfuzz/pushbackio.rb', line 26 def push(content) random_death if content.length > 0 @buffer.write(content) end end |
#random_death ⇒ Object
17 18 19 20 21 22 |
# File 'lib/rfuzz/pushbackio.rb', line 17 def random_death if $io_death_count @die_after -= 1 close if @die_after <= 0 end end |
#read(n, partial = false) ⇒ Object
First does a read from the internal buffer, and then appends anything needed from the secondary IO to complete the request. The return value is guaranteed to be a String, and never nil. If it returns a string of length 0 then there is nothing to read from the buffer (most likely closed). It will also avoid reading from a secondary that’s closed.
If partial==true then readpartial is used instead.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/rfuzz/pushbackio.rb', line 51 def read(n, partial=false) random_death r = pop(n) needs = n - r.length if needs > 0 sec = "" if partial begin protect do sec = @secondary.readpartial(needs) end rescue EOFError close end else protect { sec = @secondary.read(needs)} end r << (sec || "") # finally, if there's nothing at all returned then this is bad if r.length == 0 raise HttpClientError.new("Server returned empty response.") end end reset return r end |
#reset ⇒ Object
39 40 41 42 |
# File 'lib/rfuzz/pushbackio.rb', line 39 def reset random_death @buffer.string = @buffer.read # reset out internal buffer end |
#write(content) ⇒ Object
87 88 89 90 |
# File 'lib/rfuzz/pushbackio.rb', line 87 def write(content) random_death protect { @secondary.write(content) } end |