diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-05-13 12:59:13 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-05-13 13:08:28 -0700 |
commit | e662a7f7262cef0820c014ae533bdf199f0104d6 (patch) | |
tree | 28db73d813c4c595d08a706d0dd395258924db86 | |
parent | fdec276346fb0aa764499f7ad0483b6ba51685a5 (diff) | |
download | ruby_io_splice-e662a7f7262cef0820c014ae533bdf199f0104d6.tar.gz |
This is to be compatible with IO.copy_stream and also Rack::File since this may be used in web servers. This is NOT compatible with Ruby 1.8 since File.open doesn't coerce with #to_path on the given object.
-rw-r--r-- | io_splice.gemspec | 1 | ||||
-rw-r--r-- | lib/io/splice.rb | 11 | ||||
-rw-r--r-- | test/test_rack_file_compat.rb | 31 |
3 files changed, 40 insertions, 3 deletions
diff --git a/io_splice.gemspec b/io_splice.gemspec index c098a63..2046d11 100644 --- a/io_splice.gemspec +++ b/io_splice.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.rubyforge_project = %q{qrp} s.test_files = Dir['test/test_*.rb'] s.add_development_dependency('wrongdoc', '~> 1.5') + s.add_development_dependency('rack', '~> 1.2') # s.licenses = %w(LGPL) # accessor not compatible with older RubyGems end diff --git a/lib/io/splice.rb b/lib/io/splice.rb index 574e681..1ff2f6a 100644 --- a/lib/io/splice.rb +++ b/lib/io/splice.rb @@ -25,6 +25,11 @@ module IO::Splice n end + def self.need_open?(obj) # :nodoc: + return false if obj.respond_to?(:to_io) + obj.respond_to?(:to_path) || obj.kind_of?(String) + end + # copies the contents of the IO object given by +src+ to +dst+ # If +len+ is specified, then only +len+ bytes are copied and # +EOFError+ is raised if fewer than +len+ bytes could be copied. @@ -36,10 +41,10 @@ module IO::Splice # objects with no underlying file descriptor (e.g. StringIO). def self.copy_stream(src, dst, len = nil, src_offset = nil) close = [] - src.kind_of?(String) and close << (src = File.open(src)) - dst.kind_of?(String) and close << (dst = File.open(dst, "w")) - src, dst = src.to_io, dst.to_io + need_open?(src) and close << (src = File.open(src)) + need_open?(dst) and close << (dst = File.open(dst, "w")) rv = len + src, dst = src.to_io, dst.to_io if src.stat.pipe? || dst.stat.pipe? if len diff --git a/test/test_rack_file_compat.rb b/test/test_rack_file_compat.rb new file mode 100644 index 0000000..5505262 --- /dev/null +++ b/test/test_rack_file_compat.rb @@ -0,0 +1,31 @@ +# -*- encoding: binary -*- +require "rack" +require "test/unit" +require "socket" +require "io/splice" + +class TestRackFileCompat < Test::Unit::TestCase + def setup + @app = Rack::File.new(File.dirname(__FILE__)) + @req = Rack::MockRequest.new(@app) + @base_file = File.basename(__FILE__) + @r, @w = UNIXSocket.pair + end + + def teardown + [ @r, @w ].each { |io| io.closed? or io.close } + end + + def test_get_rack_file + env = Rack::MockRequest.env_for "http://example.com/#@base_file" + status, headers, body = @app.call(env) + assert_equal 200, status.to_i + headers.each { |k,v| + assert_instance_of String, k.to_str + assert_instance_of String, v.to_str + } + thr = Thread.new { @r.read(File.size(__FILE__)) } + assert_equal File.size(__FILE__), IO::Splice.copy_stream(body, @w) + assert_equal File.read(__FILE__), thr.value + end +end if IO.respond_to?(:copy_stream) |