module AWS::S3::DataOptions

def compute_write_options *args, &block

Returns:
  • (Hash) - Returns a hash of options with a :data option that
def compute_write_options *args, &block
  options = convert_args_to_options_hash(*args)
  validate_data!(options, &block)
  rename_file_to_data(options)
  convert_data_to_io_obj(options, &block)
  try_to_determine_content_length(options)
  options
end

def convert_args_to_options_hash *args

non-hash arguments in the first position as a data option.
Converts an argument list into a single hash of options. Treats
def convert_args_to_options_hash *args
  case args.count
  when 0 then {}
  when 1 then args[0].is_a?(Hash) ? args[0] : { :data => args[0] }
  when 2 then args[1].merge(:data => args[0])
  else
    msg = "expected 0, 1 or 2 arguments, got #{args.count}"
    raise ArgumentError, msg
  end
end

def convert_data_to_io_obj options, &block

to always perform streaming uploads.
Converts the :data option to an IO-like object. This allows us
def convert_data_to_io_obj options, &block
  data = options.delete(:data)
  if block_given?
    options[:data] = IOProxy.new(block)
  elsif data.is_a?(String)
    data = data.dup if data.frozen?
    data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
    options[:data] = StringIO.new(data)
  elsif data.is_a?(Pathname)
    options[:data] = open_file(data.to_s)
  elsif io_like?(data)
    options[:data] = data
  else
    msg = "invalid :data option, expected a String, Pathname or "
    msg << "an object that responds to #read and #eof?"
    raise ArgumentError, msg
  end
end

def io_like? io

Returns:
  • (Boolean) - Returns `true` if the object responds to
def io_like? io
  io.respond_to?(:read) and io.respond_to?(:eof?)
end

def open_file path

Returns:
  • (File) - Given a path string, returns an open File.

Parameters:
  • path (String) -- Path to a file on disk.
def open_file path
  Core::ManagedFile.open(path)
end

def rename_file_to_data options

then it is treated as a file path and is converted to an open file.
Moves options[:file] to options[:data]. If this option is a string
def rename_file_to_data options
  if file = options.delete(:file)
    options[:data] = file.is_a?(String) ? open_file(file) : file
  end
end

def try_to_determine_content_length options

This is only done when a content length is not already provided.
Attempts to determine the content length of the :data option.
def try_to_determine_content_length options
  unless options[:content_length]
    data = options[:data]
    length = case
      when data.respond_to?(:path) && data.path then File.size(data.path)
      when data.respond_to?(:bytesize) then data.bytesize
      when data.respond_to?(:size)     then data.size
      when data.respond_to?(:length)   then data.length
      else nil
    end
    options[:content_length] = length if length
  end
end

def validate_data! options, &block

def validate_data! options, &block
  data = options[:data]
  file = options[:file]
  raise ArgumentError, 'Object data passed multiple ways.' if
    [data, file, block].compact.count > 1
  data = file if file
  return if block_given?
  return if data.kind_of?(String)
  return if data.kind_of?(Pathname)
  return if io_like?(data)
  msg = ":data must be provided as a String, Pathname, File, or "
  msg << "an object that responds to #read and #eof?"
  raise ArgumentError, msg
end