# File lib/rubytorrent/package.rb, line 487
  def initialize(metainfo, out=nil, validity_assumption=nil)
    info = metainfo.info

    created = false
    out ||= info.name
    case out
    when File
      raise ArgumentError, "'out' cannot be a File for a multi-file .torrent" if info.multiple?
      fstream = out
    when Dir
      raise ArgumentError, "'out' cannot be a Dir for a single-file .torrent" if info.single?
      fstream = out
    when String
      if info.single?
        rt_debug "output file is #{out}"
        begin
          fstream = File.open(out, "rb+")
        rescue Errno::ENOENT
          created = true
          fstream = File.open(out, "wb+")
        end
      else
        rt_debug "output directory is #{out}"
        unless File.exists? out
          Dir.mkdir(out)
          created = true
        end
        fstream = Dir.open(out)
      end
    else
      raise ArgumentError, "'out' should be a File, Dir or String object, is #{out.class}"
    end

    @ro = false
    @size = info.total_length
    if info.single?
      @files = [[fstream, Mutex.new, info.length]]
    else
      @files = info.files.map do |finfo|
        path = File.join(finfo.path[0, finfo.path.length - 1].inject(fstream.path) do |path, el|
          dir = File.join(path, el)
          unless File.exist? dir
            rt_debug "making directory #{dir}"
            Dir.mkdir dir
          end
          dir
        end, finfo.path[finfo.path.length - 1])
        rt_debug "opening #{path}..."
        [open_file(path), Mutex.new, finfo.length]
      end
    end

    i = 0
    @pieces = info.pieces.unpack("a20" * (info.pieces.length / 20)).map do |hash|
      start = (info.piece_length * i)
      len = [info.piece_length, @size - start].min
      p = Piece.new(i, hash, start, len, @files, (created ? false : validity_assumption))
      p.on_event(self, :complete) { send_event(:complete) if complete? }
      yield p if block_given?
      (i += 1) && p
    end

    reopen_ro if complete?
  end