Bits

The Bits class represents an immutable sequence of bits, similar to how the built-in bytes is an immutable sequence of bytes, and a str is an immutable sequence of characters.

If you need to modify the data after creation there is also a MutableBits class, but the more efficient Bits should be preferred if the extra capabilities are not needed.

You can switch between Bits and MutableBits using the Bits.to_mutable_bits and MutableBits.to_bits methods.


class Bits(s=None)

An immutable container of binary data.

To construct, use a builder ‘from’ method:

  • Bits.from_bytes(b) - Create directly from a bytes object.

  • Bits.from_string(s) - Use a formatted string.

  • Bits.from_bools(i) - Convert each element in i to a bool.

  • Bits.from_zeros(length) - Initialise with length ‘0’ bits.

  • Bits.from_ones(length) - Initialise with length ‘1’ bits.

  • Bits.from_random(length, [seed]) - Initialise with length pseudo-randomly set bits.

  • Bits.from_dtype(dtype, value) - Combine a data type with a value.

  • Bits.from_joined(iterable) - Concatenate an iterable of objects.

Using the constructor Bits(s) is an alias for Bits.from_string(s).

all()

Return True if all bits are equal to 1, otherwise return False.

Returns:

True if all bits are 1, otherwise False.

>>> Bits('0b1111').all()
True
>>> Bits('0b1011').all()
False
any()

Return True if any bits are equal to 1, otherwise return False.

Returns:

True if any bits are 1, otherwise False.

>>> Bits('0b0000').any()
False
>>> Bits('0b1000').any()
True
chunks(chunk_size, count=None)

Return Bits generator by cutting into chunks.

Parameters:
  • chunk_size – The size in bits of the chunks to generate.

  • count – If specified, at most count items are generated. Default is to cut as many times as possible.

Returns:

A generator yielding Bits chunks.

>>> list(Bits('0b110011').chunks(2))
[Bits('0b11'), Bits('0b00'), Bits('0b11')]
count(value)

Return count of total number of either zero or one bits.

Parameters:

value – If bool(value) is True, bits set to 1 are counted; otherwise, bits set to 0 are counted.

Returns:

The count of bits set to 1 or 0.

>>> Bits('0xef').count(1)
7
ends_with(suffix)

Return whether the current Bits ends with suffix.

Parameters:

suffix – The Bits to search for.

Returns:

True if the Bits ends with the suffix, otherwise False.

>>> Bits('0b101100').ends_with('0b10-')
True
>>> Bits('0b101100').ends_with('0b101')
False
find(bs, /, start=None, end=None, byte_aligned=None)

Find first occurrence of substring bs.

Returns the bit position if found, or None if not found.

Parameters:
  • bs (Union[Bits, MutableBits, str, bytearray, bytes, memoryview]) – The Bits to find.

  • start (int | None) – The starting bit position. Defaults to 0.

  • end (int | None) – The end position. Defaults to len(self).

  • byte_aligned (bool | None) – If True, the Bits will only be found on byte boundaries.

Return type:

int | None

Returns:

The bit position if found, or None if not found.

>>> Bits.from_string('0xc3e').find('0b1111')
6
find_all(bs, start=None, end=None, count=None, byte_aligned=None)

Find all occurrences of bs. Return generator of bit positions.

Parameters:
  • bs (Union[Bits, MutableBits, str, bytearray, bytes, memoryview]) – The Bits to find.

  • start (int | None) – The starting bit position of the slice to search. Defaults to 0.

  • end (int | None) – The end bit position of the slice to search. Defaults to len(self).

  • count (int | None) – The maximum number of occurrences to find.

  • byte_aligned (bool | None) – If True, the Bits will only be found on byte boundaries.

Return type:

Iterable[int]

Returns:

A generator yielding bit positions.

Raises ValueError if bs is empty, if start < 0, if end > len(self) or if end < start.

All occurrences of bs are found, even if they overlap.

Note that this method is not available for MutableBits as its value could change while the generator is still active. For that case you should convert to a Bits first with MutableBits.to_bits.

>>> list(Bits('0b10111011').find_all('0b11'))
[2, 3, 6]
from_bools()

Create a new instance from an iterable by converting each element to a bool.

Parameters:

i – The iterable to convert to a Bits.

a = Bits.from_bools([False, 0, 1, "Steven"])  # binary 0011
from_bytes()

Create a new instance from a bytes object.

Parameters:

b – The bytes object to convert to a Bits.


a = Bits.from_bytes(b”some_bytes_maybe_from_a_file”)

classmethod from_dtype(dtype, value, /)

Pack a value according to a data type or data type tuple.

Parameters:
  • dtype (Dtype | str) – The data type to pack.

  • value (Any) – A value appropriate for the data type.

Return type:

Bits

Returns:

A newly constructed Bits.

a = Bits.from_dtype("u8", 17)
b = Bits.from_dtype("f16, i4, bool", [2.25, -3, False])
from_joined()

Create a new instance by concatenating a sequence of Bits objects.

This method concatenates a sequence of Bits objects into a single Bits object.

Parameters:

sequence – A sequence to concatenate. Items can either be a Bits object, or a string or bytes-like object that could create one via the from_string or from_bytes methods.

a = Bits.from_joined([f'u6={x}' for x in range(64)])
b = Bits.from_joined(['0x01', 'i4 = -1', b'some_bytes'])
from_ones()

Create a new instance with all bits set to ‘1’.

Parameters:

length – The number of bits to set.

>>> Bits.from_ones(5)
Bits('0b11111')
from_random(seed=None)

Create a new instance with all bits pseudo-randomly set.

Parameters:
  • length – The number of bits to set. Must be positive.

  • seed – An optional seed as a bytes or bytearray.

Returns:

A newly constructed Bits with random data.

Note that this uses a pseudo-random number generator and so might not suitable for cryptographic or other more serious purposes.

a = Bits.from_random(1000000)  # A million random bits
b = Bits.from_random(100, b'a_seed')
from_string()

Create a new instance from a formatted string.

This method initializes a new instance of Bits using a formatted string.

Parameters:

s – The formatted string to convert.

Returns:

A newly constructed Bits.

a = Bits.from_string("0xff01")
b = Bits.from_string("0b1")
c = Bits.from_string("u12 = 31, f16=-0.25")

The __init__ method for Bits redirects to the from_string method and is sometimes more convenient:

a = Bits("0xff01")  # Bits(s) is equivalent to Bits.from_string(s)
from_zeros()

Create a new instance with all bits set to ‘0’.

Parameters:

length – The number of bits to set.

Returns:

A Bits object with all bits set to zero.

a = Bits.from_zeros(500)  # 500 zero bits
info()

Return a descriptive string with information about the Bits.

Note that the output is designed to be helpful to users and is not considered part of the API. You should not use the output programmatically as it may change even between point versions.

>>> Bits('0b1101').info()
'4 bits: binary = 1101, hex = d, unsigned int = 13, signed int = -3'
Return type:

str

pp(dtype1=None, dtype2=None, groups=None, width=80, show_offset=True, stream=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>)

Pretty print the Bits’s value.

Parameters:
  • dtype1 (str | Dtype | None) – First data type to display.

  • dtype2 (str | Dtype | None) – Optional second data type.

  • groups (int | None) – How many groups of bits to display on each line. This overrides any value given for width.

  • width (int) – Max width of printed lines. Defaults to 80, but ignored if groups parameter is set. A single group will always be printed per line even if it exceeds the max width.

  • show_offset (bool) – If True (the default) shows the bit offset in the first column of each line.

  • stream (TextIO) – A TextIO object with a write() method. Defaults to sys.stdout.

Return type:

None

s.pp('hex4', groups=6)
s.pp('bin', 'hex', show_offset=False)
rfind(bs, /, start=None, end=None, byte_aligned=None)

Find final occurrence of substring bs.

Returns the bit position if found, or None if not found. Note that start and end define a slice in the usual way, so the occurrence of bs closest to the end posistion will be found.

Parameters:
  • bs (Union[Bits, MutableBits, str, bytearray, bytes, memoryview]) – The Bits to find.

  • start (int | None) – The starting bit position of the slice to search. Defaults to 0.

  • end (int | None) – The end bit position of the slice to search. Defaults to len(self).

  • byte_aligned (bool | None) – If True, the Bits will only be found on byte boundaries.

Return type:

int | None

Returns:

The bit position if found, or None if not found.

Raises ValueError if bs is empty.

>>> Bits('0b110110').rfind('0b1')
4
>>> Bits('0b110110').rfind('0b0')
5
rfind_all(bs, start=None, end=None, count=None, byte_aligned=None)

Find all occurrences of bs starting at the end. Return generator of bit positions.

Parameters:
  • bs (Union[Bits, MutableBits, str, bytearray, bytes, memoryview]) – The Bits to find.

  • start (int | None) – The starting bit position of the slice to search. Defaults to 0.

  • end (int | None) – The end bit position of the slice to search. Defaults to len(self).

  • count (int | None) – The maximum number of occurrences to find.

  • byte_aligned (bool | None) – If True, the Bits will only be found on byte boundaries.

Return type:

Iterable[int]

Returns:

A generator yielding bit positions.

Raises ValueError if bs is empty, if start < 0, if end > len(self) or if end < start.

All occurrences of bs are found, even if they overlap.

Note that this method is not available for MutableBits as its value could change while the generator is still active. For that case you should convert to a Bits first with MutableBits.to_bits.

>>> list(Bits('0b10111011').rfind_all('0b11'))
[6, 3, 2]
starts_with(prefix)

Return whether the current Bits starts with prefix.

Parameters:

prefix – The Bits to search for.

Returns:

True if the Bits starts with the prefix, otherwise False.

>>> Bits('0b101100').starts_with('0b101')
True
>>> Bits('0b101100').starts_with('0b100')
False
to_bytes()

Return the Bits as bytes, padding with zero bits if needed.

Up to seven zero bits will be added at the end to byte align.

Returns:

The Bits as bytes.

to_mutable_bits()

Create and return a mutable copy of the Bits as a MutableBits instance.

unpack(dtype, /, start=None, end=None)

Interpret the Bits as a given data type or list of data types.

If a single Dtype is given then a single value will be returned, otherwise a list of values will be returned. A single Dtype with no length can be used to interpret the whole Bits - in this common case properties are provided as a shortcut. For example instead of b.unpack('bin') you can use b.bin.

Parameters:
  • dtype (Dtype | str | Sequence[Dtype | str]) – The data type used to interpret the Bits.

  • start (int | None) – The starting bit position. Defaults to 0.

  • end (int | None) – The end position. Defaults to len(self).

Return type:

Any | list[Any]

Returns:

The interpreted value(s).

>>> s = Bits('0xdeadbeef')
>>> s.unpack(['bin4', 'u28'])
['1101', 246267631]
>>> s.unpack(['f16', '[u4; 4]'])
[-427.25, (11, 14, 14, 15)]
>>> s.unpack('i')
-559038737
>>> s.i
-559038737
property bin

The Bits as a binary string. Read only.

property bits

The Bits as a Bits object. Read only.

property bool

The Bits as a bool (True or False). Read only.

property bytes

The Bits as a bytes object. Read only.

property f

The Bits as an IEEE floating point number. Read only.

property f_be

The Bits as an IEEE floating point number in big-endian byte order. Read only.

property f_le

The Bits as an IEEE floating point number in little-endian byte order. Read only.

property f_ne

The Bits as an IEEE floating point number in native-endian (i.e. little-endian-endian) byte order. Read only.

property hex

The Bits as a hexadecimal string. Read only.

property i

The Bits as a two’s complement signed int. Read only.

property i_be

The Bits as a two’s complement signed int in big-endian byte order. Read only.

property i_le

The Bits as a two’s complement signed int in little-endian byte order. Read only.

property i_ne

The Bits as a two’s complement signed int in native-endian (i.e. little-endian-endian) byte order. Read only.

property oct

The Bits as an octal string. Read only.

property pad

The Bits as a skipped section of padding. Read only.

property u

The Bits as a two’s complement unsigned int. Read only.

property u_be

The Bits as a two’s complement unsigned int in big-endian byte order. Read only.

property u_le

The Bits as a two’s complement unsigned int in little-endian byte order. Read only.

property u_ne

The Bits as a two’s complement unsigned int in native-endian (i.e. little-endian-endian) byte order. Read only.