lib/em-http/decoders.rb in em-http-request-1.0.2 vs lib/em-http/decoders.rb in em-http-request-1.0.3
- old
+ new
@@ -8,11 +8,11 @@
class DecoderError < StandardError
end
class << self
def accepted_encodings
- DECODERS.inject([]) { |r,d| r + d.encoding_names }
+ DECODERS.inject([]) { |r, d| r + d.encoding_names }
end
def decoder_for_encoding(encoding)
DECODERS.each { |d|
return d if d.encoding_names.include? encoding
@@ -42,11 +42,11 @@
def finalize!
decompressed = finalize
receive_decompressed decompressed
end
-
+
private
def receive_decompressed(decompressed)
if decompressed && decompressed.size > 0
@chunk_callback.call(decompressed)
@@ -89,31 +89,53 @@
raise DecoderError
end
end
end
- ##
- # Oneshot decompressor, due to lack of a streaming Gzip reader
- # implementation. We may steal code from Zliby to improve this.
- #
- # For now, do not put `gzip' or `compressed' in your accept-encoding
- # header if you expect much data through the :on_response interface.
class GZip < Base
def self.encoding_names
%w(gzip compressed)
end
def decompress(compressed)
- @buf ||= ''
- @buf += compressed
- nil
+ @buf ||= LazyStringIO.new
+ @buf << compressed
+
+ # Zlib::GzipReader loads input in 2048 byte chunks
+ if @buf.size > 2048
+ @gzip ||= Zlib::GzipReader.new @buf
+ @gzip.readline
+ end
end
def finalize
begin
- Zlib::GzipReader.new(StringIO.new(@buf.to_s)).read
+ @gzip ||= Zlib::GzipReader.new @buf
+ @gzip.read
rescue Zlib::Error
raise DecoderError
+ end
+ end
+
+ class LazyStringIO
+ def initialize(string="")
+ @stream = string
+ end
+
+ def <<(string)
+ @stream << string
+ end
+
+ def read(length=nil, buffer=nil)
+ buffer ||= ""
+ length ||= 0
+ buffer << @stream[0..(length-1)]
+ @stream = @stream[length..-1]
+ buffer
+ end
+
+ def size
+ @stream.size
end
end
end
DECODERS = [Deflate, GZip]