Use duck typing to detect IO-like objects.
This commit is contained in:
parent
1a028fcbaa
commit
05a9ba3f20
|
@ -176,7 +176,7 @@ module Zip
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_c_dir_entry(io) #:nodoc:all
|
def read_c_dir_entry(io) #:nodoc:all
|
||||||
path = if io.is_a?(::IO)
|
path = if io.respond_to?(:path)
|
||||||
io.path
|
io.path
|
||||||
else
|
else
|
||||||
io
|
io
|
||||||
|
@ -548,7 +548,7 @@ module Zip
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_raw_input_stream(&block)
|
def get_raw_input_stream(&block)
|
||||||
if @zipfile.is_a?(::IO) || @zipfile.is_a?(::StringIO)
|
if @zipfile.respond_to?(:seek) && @zipfile.respond_to?(:read)
|
||||||
yield @zipfile
|
yield @zipfile
|
||||||
else
|
else
|
||||||
::File.open(@zipfile, 'rb', &block)
|
::File.open(@zipfile, 'rb', &block)
|
||||||
|
|
|
@ -49,6 +49,7 @@ module Zip
|
||||||
MAX_SEGMENT_SIZE = 3_221_225_472
|
MAX_SEGMENT_SIZE = 3_221_225_472
|
||||||
MIN_SEGMENT_SIZE = 65_536
|
MIN_SEGMENT_SIZE = 65_536
|
||||||
DATA_BUFFER_SIZE = 8192
|
DATA_BUFFER_SIZE = 8192
|
||||||
|
IO_METHODS = [:tell, :seek, :read, :close]
|
||||||
|
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
|
@ -117,13 +118,13 @@ module Zip
|
||||||
# (This can be used to extract data from a
|
# (This can be used to extract data from a
|
||||||
# downloaded zip archive without first saving it to disk.)
|
# downloaded zip archive without first saving it to disk.)
|
||||||
def open_buffer(io, options = {})
|
def open_buffer(io, options = {})
|
||||||
unless io.is_a?(IO) || io.is_a?(String) || io.is_a?(Tempfile) || io.is_a?(StringIO)
|
unless IO_METHODS.map { |method| io.respond_to?(method) }.all? || io.is_a?(String)
|
||||||
raise "Zip::File.open_buffer expects an argument of class String, IO, StringIO, or Tempfile. Found: #{io.class}"
|
raise "Zip::File.open_buffer expects a String or IO-like argument (responds to #{IO_METHODS.join(', ')}). Found: #{io.class}"
|
||||||
end
|
end
|
||||||
if io.is_a?(::String)
|
if io.is_a?(::String)
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
io = ::StringIO.new(io)
|
io = ::StringIO.new(io)
|
||||||
elsif io.is_a?(IO)
|
elsif io.respond_to?(:binmode)
|
||||||
# https://github.com/rubyzip/rubyzip/issues/119
|
# https://github.com/rubyzip/rubyzip/issues/119
|
||||||
io.binmode
|
io.binmode
|
||||||
end
|
end
|
||||||
|
|
|
@ -111,8 +111,7 @@ module Zip
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def get_io(io_or_file, offset = 0)
|
def get_io(io_or_file, offset = 0)
|
||||||
case io_or_file
|
if io_or_file.respond_to?(:seek)
|
||||||
when IO, StringIO
|
|
||||||
io = io_or_file.dup
|
io = io_or_file.dup
|
||||||
io.seek(offset, ::IO::SEEK_SET)
|
io.seek(offset, ::IO::SEEK_SET)
|
||||||
io
|
io
|
||||||
|
|
|
@ -3,6 +3,16 @@ require 'test_helper'
|
||||||
class ZipInputStreamTest < MiniTest::Test
|
class ZipInputStreamTest < MiniTest::Test
|
||||||
include AssertEntry
|
include AssertEntry
|
||||||
|
|
||||||
|
class IOLike
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
def initialize(path, mode)
|
||||||
|
@file = File.new(path, mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
delegate ::Zip::File::IO_METHODS => :@file
|
||||||
|
end
|
||||||
|
|
||||||
def test_new
|
def test_new
|
||||||
zis = ::Zip::InputStream.new(TestZipFile::TEST_ZIP2.zip_name)
|
zis = ::Zip::InputStream.new(TestZipFile::TEST_ZIP2.zip_name)
|
||||||
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
||||||
|
@ -48,6 +58,13 @@ class ZipInputStreamTest < MiniTest::Test
|
||||||
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_open_io_like_with_block
|
||||||
|
::Zip::InputStream.open(IOLike.new(TestZipFile::TEST_ZIP2.zip_name, 'rb')) do |zis|
|
||||||
|
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
||||||
|
assert_equal(true, zis.eof?)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_incomplete_reads
|
def test_incomplete_reads
|
||||||
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
||||||
entry = zis.get_next_entry # longAscii.txt
|
entry = zis.get_next_entry # longAscii.txt
|
||||||
|
|
Loading…
Reference in New Issue