public function copy($source)
    {
        if (! $this->resource) {
            throw new RuntimeException('No resource available; cannot copy.');
        }
        $resource = null;
        if ($source instanceof self) {
            $resource = $source->getResource();
        } elseif (is_resource($source)) {
            $resource = $source;
        } elseif (is_string($source)) {
            set_error_handler(function () {
                throw new Exception('Failed to open stream.');
            });
            try {
                $resource = fopen($source, 'rb');
            } catch (Exception $ex) {
                restore_error_handler();
                throw new InvalidArgumentException(sprintf(
                    'Invalid source path "%s" specified.',
                    $source
                ));
            }
            restore_error_handler();
        } else {
            throw new InvalidArgumentException(sprintf(
                'Invalid source "%s" provided.',
                is_object($source) ? get_class($source) : gettype($source)
            ));
        }
        $metadata = stream_get_meta_data($resource);
        $mode     = $metadata['mode'];
        if (! (strstr($mode, 'r') || strstr($mode, '+'))) {
            throw new InvalidArgumentException(
                'The received source is not readable.'
            );
        }
        $seekable = $metadata['seekable'];
        if ($seekable) {
            rewind($resource);
        }
        stream_copy_to_stream($resource, $this->resource);
        rewind($this->resource);
        if (is_string($source)) {
            fclose($resource);
        }
    }