Fill the buffer with bytes from source until one of these
        conditions is met:
            * size bytes have been read from source (if size >= 0);
            * chunk_size bytes have been read from source;
            * no more bytes can be read from source;
        Returns the number of new bytes added to the buffer.
        Note: all previously-read bytes in the buffer are removed.

        Parameters
        ----------
        source: a file-like object, or iterable/list that contains bytes
            The source of bytes to fill the buffer with. If this argument has
            the `read` attribute, it's assumed to be a file-like object and
            `read` is called to get the bytes; otherwise it's assumed to be an
            iterable or list that contains bytes, and a for loop is used to get
            the bytes.
        size: int, optional
            The number of bytes to try to read from source. If not supplied,
            negative, or larger than the buffer's chunk_size, then chunk_size
            bytes are read. Note that if source is an iterable or list, then
            it's possible that more than size bytes will be read if iterating
            over source produces more than one byte at a time.

        Returns
        -------
        int, the number of new bytes added to the buffer.

def fill(self, source, size=-1):
        """Fill the buffer with bytes from source until one of these
        conditions is met:
            * size bytes have been read from source (if size >= 0);
            * chunk_size bytes have been read from source;
            * no more bytes can be read from source;
        Returns the number of new bytes added to the buffer.
        Note: all previously-read bytes in the buffer are removed.

        Parameters
        ----------
        source: a file-like object, or iterable/list that contains bytes
            The source of bytes to fill the buffer with. If this argument has
            the `read` attribute, it's assumed to be a file-like object and
            `read` is called to get the bytes; otherwise it's assumed to be an
            iterable or list that contains bytes, and a for loop is used to get
            the bytes.
        size: int, optional
            The number of bytes to try to read from source. If not supplied,
            negative, or larger than the buffer's chunk_size, then chunk_size
            bytes are read. Note that if source is an iterable or list, then
            it's possible that more than size bytes will be read if iterating
            over source produces more than one byte at a time.

        Returns
        -------
        int, the number of new bytes added to the buffer.
        """
        size = size if size >= 0 else self._chunk_size
        size = min(size, self._chunk_size)

        if self._pos != 0:
            self._bytes = self._bytes[self._pos:]
            self._pos = 0

        if hasattr(source, 'read'):
            new_bytes = source.read(size)
        else:
            new_bytes = b''
            for more_bytes in source:
                new_bytes += more_bytes
                if len(new_bytes) >= size:
                    break

        self._bytes += new_bytes
        return len(new_bytes)