Class: Tubeclip::ChainIO
- Inherits:
-
Object
- Object
- Tubeclip::ChainIO
- Defined in:
- lib/tubeclip/chain_io.rb
Overview
Stream wrapper that reads IOs in succession. Can be fed to Net::HTTP as post body stream. We use it internally to stream file content instead of reading whole video files into memory. Strings passed to the constructor will be wrapped in StringIOs. By default it will auto-close file handles when they have been read completely to prevent our uploader from leaking file handles
chain = ChainIO.new(File.open(__FILE__), File.open(‘/etc/passwd’), “abcd”)
Direct Known Subclasses
Instance Attribute Summary collapse
-
#autoclose ⇒ Object
Returns the value of attribute autoclose.
Instance Method Summary collapse
-
#expected_length ⇒ Object
Predict the length of all embedded IOs.
-
#initialize(*any_ios) ⇒ ChainIO
constructor
A new instance of ChainIO.
- #read(buffer_size = 1024) ⇒ Object
Constructor Details
#initialize(*any_ios) ⇒ ChainIO
Returns a new instance of ChainIO.
12 13 14 15 |
# File 'lib/tubeclip/chain_io.rb', line 12 def initialize(*any_ios) @autoclose = true @chain = any_ios.flatten.map{|e| e.respond_to?(:read) ? e : StringIO.new(e.to_s) } end |
Instance Attribute Details
#autoclose ⇒ Object
Returns the value of attribute autoclose.
10 11 12 |
# File 'lib/tubeclip/chain_io.rb', line 10 def autoclose @autoclose end |
Instance Method Details
#expected_length ⇒ Object
Predict the length of all embedded IOs. Will automatically send file size.
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/tubeclip/chain_io.rb', line 39 def expected_length @chain.inject(0) do | len, io | if io.respond_to?(:length) len + (io.length - io.pos) elsif io.is_a?(File) len + File.size(io.path) - io.pos else raise "Cannot predict length of #{io.inspect}" end end end |
#read(buffer_size = 1024) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/tubeclip/chain_io.rb', line 17 def read(buffer_size = 1024) # Read off the first element in the stack current_io = @chain.shift return false if !current_io buf = current_io.read(buffer_size) if !buf && @chain.empty? # End of streams release_handle(current_io) if @autoclose false elsif !buf # This IO is depleted, but next one is available release_handle(current_io) if @autoclose read(buffer_size) elsif buf.length < buffer_size # This IO is depleted, but we were asked for more release_handle(current_io) if @autoclose buf + (read(buffer_size - buf.length) || '') # and recurse else # just return the buffer @chain.unshift(current_io) # put the current back buf end end |