simplified the compression API, sharing more across compressors

This commit is contained in:
HoneyryderChuck 2018-01-14 20:38:14 +00:00
parent 8b45c626ce
commit 6319d83b81
4 changed files with 50 additions and 34 deletions

View File

@ -44,10 +44,11 @@ module HTTPX
class CompressEncoder class CompressEncoder
attr_reader :content_type attr_reader :content_type
def initialize(raw) def initialize(raw, encoder)
@content_type = raw.content_type @content_type = raw.content_type
@raw = raw.respond_to?(:read) ? raw : StringIO.new(raw.to_s) @raw = raw.respond_to?(:read) ? raw : StringIO.new(raw.to_s)
@buffer = StringIO.new("".b, File::RDWR) @buffer = StringIO.new("".b, File::RDWR)
@encoder = encoder
end end
def each(&blk) def each(&blk)
@ -56,7 +57,7 @@ module HTTPX
@buffer.rewind @buffer.rewind
return @buffer.each(&blk) return @buffer.each(&blk)
end end
compress(&blk) @encoder.compress(@raw, @buffer, &blk)
end end
def to_s def to_s
@ -66,7 +67,7 @@ module HTTPX
end end
def bytesize def bytesize
compress @encoder.compress(@raw, @buffer)
@buffer.size @buffer.size
end end

View File

@ -22,18 +22,33 @@ module HTTPX
end end
end end
module Encoder
module_function
def compress(raw, buffer, chunk_size: 16_384)
return unless buffer.size.zero?
raw.rewind
begin
while chunk = raw.read(chunk_size)
compressed = ::Brotli.deflate(chunk)
buffer << compressed
yield compressed if block_given?
end
end
end
end
module BrotliTranscoder module BrotliTranscoder
module_function module_function
def encode(payload) def encode(payload)
::Brotli.deflate(payload) CompressEncoder.new(payload, Encoder)
end end
def decode(io) def decode(io)
::Brotli.inflate(io) ::Brotli.inflate(io)
end end
end end
end end
end end
register_plugin :"compression/brotli", Compression::Brotli register_plugin :"compression/brotli", Compression::Brotli

View File

@ -15,24 +15,24 @@ module HTTPX
end end
module DeflateTranscoder module DeflateTranscoder
class Encoder < CompressEncoder module Encoder
private module_function
def compress def compress(raw, buffer, chunk_size: 16_384)
return unless @buffer.size.zero? return unless buffer.size.zero?
@raw.rewind raw.rewind
begin begin
deflater = Zlib::Deflate.new(Zlib::BEST_COMPRESSION, deflater = Zlib::Deflate.new(Zlib::BEST_COMPRESSION,
Zlib::MAX_WBITS, Zlib::MAX_WBITS,
Zlib::MAX_MEM_LEVEL, Zlib::MAX_MEM_LEVEL,
Zlib::HUFFMAN_ONLY) Zlib::HUFFMAN_ONLY)
while chunk = @raw.read(16_384) while chunk = raw.read(chunk_size)
compressed = deflater.deflate(chunk) compressed = deflater.deflate(chunk)
@buffer << compressed buffer << compressed
yield compressed if block_given? yield compressed if block_given?
end end
last = deflater.finish last = deflater.finish
@buffer << last buffer << last
yield last if block_given? yield last if block_given?
ensure ensure
deflater.close deflater.close
@ -70,7 +70,7 @@ module HTTPX
end end
def encode(payload) def encode(payload)
Encoder.new(payload) CompressEncoder.new(payload, Encoder)
end end
def decode(io) def decode(io)

View File

@ -14,43 +14,43 @@ module HTTPX
end end
module GZIPTranscoder module GZIPTranscoder
class Encoder < CompressEncoder class Encoder
def write(chunk) def compress(raw, buffer, chunk_size: 16_384)
@compressed_chunk = chunk return unless buffer.size.zero?
end raw.rewind
private
def compressed_chunk
compressed = @compressed_chunk
compressed
ensure
@compressed_chunk = nil
end
def compress
return unless @buffer.size.zero?
@raw.rewind
begin begin
gzip = Zlib::GzipWriter.new(self) gzip = Zlib::GzipWriter.new(self)
while chunk = @raw.read(16_384) while chunk = raw.read(chunk_size)
gzip.write(chunk) gzip.write(chunk)
gzip.flush gzip.flush
compressed = compressed_chunk compressed = compressed_chunk
@buffer << compressed buffer << compressed
yield compressed if block_given? yield compressed if block_given?
end end
ensure ensure
gzip.close gzip.close
end end
end end
private
def write(chunk)
@compressed_chunk = chunk
end
def compressed_chunk
compressed = @compressed_chunk
compressed
ensure
@compressed_chunk = nil
end
end end
module_function module_function
def encode(payload) def encode(payload)
Encoder.new(payload) CompressEncoder.new(payload, Encoder.new)
end end
def decode(io) def decode(io)