Extracts a part of a BinArray's data and converts it to a BinArray
        of a different width.

        For the purposes of this conversion, words in this BinArray are joined
        side-by-side, starting from a given start index (defaulting to 0),
        skipping ``start_bit`` first bits of the first word, then the resulting
        stream is split into ``to_width``-sized words and ``length`` first
        such words are returned as a new BinArray.

        If ``msb_first`` is False, everything proceeds with little endian
        ordering: the first word provides the least significant bits of the
        combined stream, ``start_bit`` skips bits starting from the LSB,
        and the first output word is made from the lowest bits of the combined
        stream.  Otherwise (``msb_first`` is True), everything proceeds
        with big endian ordering: the first word provides the most
        significant bits of the combined stream, ``start_bit`` skips bits
        starting from the MSB, and the first output word is made from the
        highest bits of the combined stream.

        ``start_bits`` must be smaller than the width of the input word.
        It is an error to request a larger length than can be provided from
        the input array.  If ``length`` is not provided, this function
        returns as many words as can be extracted.

        For example, consider a 10-to-3 repack with start_bit=2, length=4
        msb_first=True:

        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | MSB ... LSB       |
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start   |X|X|a|b|c|d|e|f|g|h|
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start+1 |i|j|k|l|X|X|X|X|X|X|
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+

        is repacked to:

        +-+-+-+-+
        |0|a|b|c|
        +-+-+-+-+
        |1|d|e|f|
        +-+-+-+-+
        |2|g|h|i|
        +-+-+-+-+
        |3|j|k|l|
        +-+-+-+-+

        The same repack for msb_first=False is performed as follows:

        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | MSB ... LSB       |
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start   |h|g|f|e|d|c|b|a|X|X|
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start+1 |X|X|X|X|X|X|l|k|j|i|
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+

        into:

        +-+-+-+-+
        |0|c|b|a|
        +-+-+-+-+
        |1|f|e|d|
        +-+-+-+-+
        |2|i|h|g|
        +-+-+-+-+
        |3|l|k|j|
        +-+-+-+-+

def repack(self, to_width, *, msb_first, start=0, start_bit=0,
               length=None):
        """Extracts a part of a BinArray's data and converts it to a BinArray
        of a different width.

        For the purposes of this conversion, words in this BinArray are joined
        side-by-side, starting from a given start index (defaulting to 0),
        skipping ``start_bit`` first bits of the first word, then the resulting
        stream is split into ``to_width``-sized words and ``length`` first
        such words are returned as a new BinArray.

        If ``msb_first`` is False, everything proceeds with little endian
        ordering: the first word provides the least significant bits of the
        combined stream, ``start_bit`` skips bits starting from the LSB,
        and the first output word is made from the lowest bits of the combined
        stream.  Otherwise (``msb_first`` is True), everything proceeds
        with big endian ordering: the first word provides the most
        significant bits of the combined stream, ``start_bit`` skips bits
        starting from the MSB, and the first output word is made from the
        highest bits of the combined stream.

        ``start_bits`` must be smaller than the width of the input word.
        It is an error to request a larger length than can be provided from
        the input array.  If ``length`` is not provided, this function
        returns as many words as can be extracted.

        For example, consider a 10-to-3 repack with start_bit=2, length=4
        msb_first=True:

        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | MSB ... LSB       |
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start   |X|X|a|b|c|d|e|f|g|h|
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start+1 |i|j|k|l|X|X|X|X|X|X|
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+

        is repacked to:

        +-+-+-+-+
        |0|a|b|c|
        +-+-+-+-+
        |1|d|e|f|
        +-+-+-+-+
        |2|g|h|i|
        +-+-+-+-+
        |3|j|k|l|
        +-+-+-+-+

        The same repack for msb_first=False is performed as follows:

        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | MSB ... LSB       |
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start   |h|g|f|e|d|c|b|a|X|X|
        +---------+-+-+-+-+-+-+-+-+-+-+
        | start+1 |X|X|X|X|X|X|l|k|j|i|
        +---------+-+-+-+-+-+-+-+-+-+-+
        |         | ...               |
        +---------+-+-+-+-+-+-+-+-+-+-+

        into:

        +-+-+-+-+
        |0|c|b|a|
        +-+-+-+-+
        |1|f|e|d|
        +-+-+-+-+
        |2|i|h|g|
        +-+-+-+-+
        |3|l|k|j|
        +-+-+-+-+
        """
        to_width = operator.index(to_width)
        if not isinstance(msb_first, bool):
            raise TypeError('msb_first must be a bool')
        available = self.repack_data_available(
                to_width, start=start, start_bit=start_bit)
        if length is None:
            length = available
        else:
            length = operator.index(length)
            if length > available:
                raise ValueError('not enough data available')
            if length < 0:
                raise ValueError('length cannot be negative')
        start = operator.index(start)
        start_bit = operator.index(start_bit)
        pos = start
        accum = BinWord(0, 0)
        if start_bit:
            accum = self[pos]
            pos += 1
            rest = accum.width - start_bit
            if msb_first:
                accum = accum.extract(0, rest)
            else:
                accum = accum.extract(start_bit, rest)
        res = BinArray(width=to_width, length=length)
        for idx in range(length):
            while len(accum) < to_width:
                cur = self[pos]
                pos += 1
                if msb_first:
                    accum = BinWord.concat(cur, accum)
                else:
                    accum = BinWord.concat(accum, cur)
            rest = accum.width - to_width
            if msb_first:
                cur = accum.extract(rest, to_width)
                accum = accum.extract(0, rest)
            else:
                cur = accum.extract(0, to_width)
                accum = accum.extract(to_width, rest)
            res[idx] = cur
        return res