Class: YouTubeIt::ChainIO
- Inherits:
-
Object
- Object
- YouTubeIt::ChainIO
- Defined in:
- lib/youtube_it/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)
-
- (Object) autoclose
Returns the value of attribute autoclose.
Instance Method Summary (collapse)
-
- (Object) expected_length
Predict the length of all embedded IOs.
-
- (ChainIO) initialize(*any_ios)
constructor
A new instance of ChainIO.
- - (Object) read(buffer_size = 1024)
Constructor Details
- (ChainIO) initialize(*any_ios)
A new instance of ChainIO
12 13 14 15 |
# File 'lib/youtube_it/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
- (Object) autoclose
Returns the value of attribute autoclose
10 11 12 |
# File 'lib/youtube_it/chain_io.rb', line 10 def autoclose @autoclose end |
Instance Method Details
- (Object) expected_length
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/youtube_it/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 |
- (Object) read(buffer_size = 1024)
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/youtube_it/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 |