lib/s3io/wrapper.rb in s3io-0.0.2 vs lib/s3io/wrapper.rb in s3io-1.0.0

- old
+ new

@@ -1,88 +1,44 @@ module S3io - # This class wraps an AWS S3 object in order to provide IO-like API. - # S3 objects wrapped this way can be used in methods that would otherwise expect an instance of File, StringIO etc. - class Wrapper - # Default buffer size for line parser in bytes - LINE_BUFFER_SIZE = 5 * 1024 * 1024 # MiB + def self.open(s3object, mode_string = 'r', options = {}, &block) + wrapper_class = case mode_string + when 'r' + ReadWrapper + when 'w' + WriteWrapper + else + fail "S3IO only supports 'r' or 'w' as access modes" + end - include Enumerable + wrapper = wrapper_class.new(s3object, options) - # Current byte position in S3 object - attr_accessor :pos + if block_given? + result = yield wrapper if block_given? + wrapper.close - # Options that were passed during initialization - attr_reader :options + return result + else + return wrapper + end + end + # This class wraps an AWS S3 object in order to provide IO-like API. + # S3 objects wrapped this way can be used in methods that would otherwise expect an instance of File, StringIO etc. + class Wrapper + # Wraps an AWS::S3::S3Object into IO-like object. # # @param [AWS::S3::S3Object] s3object an object to wrap - # @param [Hash] options options hash - # @option options [Integer] :line_buffer_size size of the buffer that is used for reading contents of S3 object when iterating over its lines - def initialize(s3object, options = {}) + def initialize(s3object) @s3object = s3object - @options = { - :line_buffer_size => (options[:line_buffer_size] || LINE_BUFFER_SIZE) - } - @pos = 0 end - # Reads data from S3 object. - # - # @param [Integer] bytes number of bytes to read - def read(bytes = nil) - content_length = @s3object.content_length - - return '' if (@pos >= content_length) || (bytes == 0) - - bytes ||= content_length - - upper_bound = @pos + bytes - 1 - upper_bound = (content_length - 1) if upper_bound >= content_length - - data = @s3object.read :range => @pos..upper_bound - @pos = upper_bound + 1 - - return data - end - - # Rewinds position to the very beginning of S3 object. - def rewind + def close + @s3object = nil @pos = 0 - end - # Iterates over S3 object lines. - # - # @param [String] separator line separator string - def each(separator = $/) - return enum_for(:each, separator) unless block_given? - - line = '' - newline_pos = nil - - # Either trying to parse the remainder or reading some more data - while newline_pos || !(buffer = read(@options[:line_buffer_size])).empty? - prev_newline_pos = newline_pos || 0 - newline_pos = buffer.index(separator, prev_newline_pos) - - if newline_pos - line << buffer[prev_newline_pos..newline_pos] - newline_pos += 1 - yield line - line = '' - else - line << buffer[prev_newline_pos..-1] - end - end - - # Flush the remainder if body doesn't end with separator - yield line unless line.empty? - - return self + return nil end - alias lines each - alias each_line each - end end