public long transfer(
            final FileChannel dst,
            long position,
            long count) throws IOException {

        if (dst == null) {
            return 0;
        }
        if (this.completed) {
            return 0;
        }

        long bytesRead;
        if (this.buffer.hasData()) {
            dst.position(position);
            bytesRead = this.buffer.read(dst);
        } else {
            if (this.channel.isOpen()) {
                if (position > dst.size()) {
                    throw new IOException("Position past end of file [" + position +
                            " > " + dst.size() + "]");
                }
                bytesRead = dst.transferFrom(this.channel, position, count);
                if (count > 0 && bytesRead == 0) {
                    bytesRead = this.buffer.fill(this.channel);
                }
            } else {
                bytesRead = -1;
            }
            if (bytesRead > 0) {
                this.metrics.incrementBytesTransferred(bytesRead);
            }
        }
        if (bytesRead == -1) {
            this.completed = true;
        }
        return bytesRead;
    }