def readbits(self, bits):
        if bits == 0:
            return 0
        if bits % 8 == 0 and self._bits_pending == 0:
            return self._read_bytes_aligned(bits // 8)
        out = 0
        masks = self._masks
        def transfer_bits(x, y, n, t):
            if n == t:
                return (x << t) | y, 0
            mask = masks[t]
            remainmask = masks[n - t]
            taken = ((y >> n - t) & mask)
            return (x << t) | taken, y & remainmask
        while bits > 0:
            if self._bits_pending > 0:
                assert self._partial_byte is not None
                take = min(self._bits_pending, bits)
                out, self._partial_byte = transfer_bits(out, self._partial_byte, self._bits_pending, take)
                if take == self._bits_pending:
                    self._partial_byte = None
                self._bits_pending -= take
                bits -= take
                continue
            r = self.f.read(1)
            if r == b'':
                raise EOFError
            self._partial_byte = ord(r)
            self._bits_pending = 8
        return out