Class: FastHttp::PushBackIO

Inherits:
Object
  • Object
show all
Defined in:
lib/fast_http/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

Instance Method Summary collapse

Constructor Details

#initialize(secondary) ⇒ PushBackIO

Returns a new instance of PushBackIO.



11
12
13
14
# File 'lib/fast_http/pushbackio.rb', line 11

def initialize(secondary)
  @secondary = secondary
  @buffer = StringIO.new
end

Instance Attribute Details

#secondaryObject

Returns the value of attribute secondary.



9
10
11
# File 'lib/fast_http/pushbackio.rb', line 9

def secondary
  @secondary
end

Instance Method Details

#closeObject



78
79
80
# File 'lib/fast_http/pushbackio.rb', line 78

def close
  @secondary.close rescue nil
end

#flushObject



70
71
72
# File 'lib/fast_http/pushbackio.rb', line 70

def flush
  protect { @secondary.flush }
end

#pop(n) ⇒ Object



24
25
26
27
# File 'lib/fast_http/pushbackio.rb', line 24

def pop(n)
  @buffer.rewind
  @buffer.read(n) || ""
end

#protectObject



82
83
84
85
86
87
88
# File 'lib/fast_http/pushbackio.rb', line 82

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.



18
19
20
21
22
# File 'lib/fast_http/pushbackio.rb', line 18

def push(content)
  if content.length > 0
    @buffer.write(content)
  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.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/fast_http/pushbackio.rb', line 40

def read(n, partial=false)
  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

#resetObject



29
30
31
# File 'lib/fast_http/pushbackio.rb', line 29

def reset
  @buffer.string = @buffer.read  # reset out internal buffer
end

#write(content) ⇒ Object



74
75
76
# File 'lib/fast_http/pushbackio.rb', line 74

def write(content)
  protect { @secondary.write(content) }
end