Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/bitstring/bits.py: 22%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3import numbers
4import pathlib
5import sys
6import mmap
7import struct
8import array
9import io
10from collections import abc
11import functools
12from typing import Tuple, Union, List, Iterable, Any, Optional, BinaryIO, TextIO, overload, Iterator, Type, TypeVar
13import bitarray
14import bitarray.util
15import bitstring
16from bitstring.bitstore import BitStore
17from bitstring import bitstore_helpers, utils
18from bitstring.dtypes import Dtype, dtype_register
19from bitstring.fp8 import p4binary_fmt, p3binary_fmt
20from bitstring.mxfp import e3m2mxfp_fmt, e2m3mxfp_fmt, e2m1mxfp_fmt, e4m3mxfp_saturate_fmt, e5m2mxfp_saturate_fmt
21from bitstring.bitstring_options import Colour
23# Things that can be converted to Bits when a Bits type is needed
24BitsType = Union['Bits', str, Iterable[Any], bool, BinaryIO, bytearray, bytes, memoryview, bitarray.bitarray]
26TBits = TypeVar("TBits", bound='Bits')
28# Maximum number of digits to use in __str__ and __repr__.
29MAX_CHARS: int = 250
32class Bits:
33 """A container holding an immutable sequence of bits.
35 For a mutable container use the BitArray class instead.
37 Methods:
39 all() -- Check if all specified bits are set to 1 or 0.
40 any() -- Check if any of specified bits are set to 1 or 0.
41 copy() - Return a copy of the bitstring.
42 count() -- Count the number of bits set to 1 or 0.
43 cut() -- Create generator of constant sized chunks.
44 endswith() -- Return whether the bitstring ends with a sub-string.
45 find() -- Find a sub-bitstring in the current bitstring.
46 findall() -- Find all occurrences of a sub-bitstring in the current bitstring.
47 fromstring() -- Create a bitstring from a formatted string.
48 join() -- Join bitstrings together using current bitstring.
49 pp() -- Pretty print the bitstring.
50 rfind() -- Seek backwards to find a sub-bitstring.
51 split() -- Create generator of chunks split by a delimiter.
52 startswith() -- Return whether the bitstring starts with a sub-bitstring.
53 tobitarray() -- Return bitstring as a bitarray from the bitarray package.
54 tobytes() -- Return bitstring as bytes, padding if needed.
55 tofile() -- Write bitstring to file, padding if needed.
56 unpack() -- Interpret bits using format string.
58 Special methods:
60 Also available are the operators [], ==, !=, +, *, ~, <<, >>, &, |, ^.
62 Properties:
64 [GENERATED_PROPERTY_DESCRIPTIONS]
66 len -- Length of the bitstring in bits.
68 """
69 __slots__ = ('_bitstore', '_filename')
71 def __init__(self, auto: Optional[Union[BitsType, int]] = None, /, length: Optional[int] = None,
72 offset: Optional[int] = None, **kwargs) -> None:
73 """Either specify an 'auto' initialiser:
74 A string of comma separated tokens, an integer, a file object,
75 a bytearray, a boolean iterable, an array or another bitstring.
77 Or initialise via **kwargs with one (and only one) of:
78 bin -- binary string representation, e.g. '0b001010'.
79 hex -- hexadecimal string representation, e.g. '0x2ef'
80 oct -- octal string representation, e.g. '0o777'.
81 bytes -- raw data as a bytes object, for example read from a binary file.
82 int -- a signed integer.
83 uint -- an unsigned integer.
84 float / floatbe -- a big-endian floating point number.
85 bool -- a boolean (True or False).
86 se -- a signed exponential-Golomb code.
87 ue -- an unsigned exponential-Golomb code.
88 sie -- a signed interleaved exponential-Golomb code.
89 uie -- an unsigned interleaved exponential-Golomb code.
90 floatle -- a little-endian floating point number.
91 floatne -- a native-endian floating point number.
92 bfloat / bfloatbe - a big-endian bfloat format 16-bit floating point number.
93 bfloatle -- a little-endian bfloat format 16-bit floating point number.
94 bfloatne -- a native-endian bfloat format 16-bit floating point number.
95 intbe -- a signed big-endian whole byte integer.
96 intle -- a signed little-endian whole byte integer.
97 intne -- a signed native-endian whole byte integer.
98 uintbe -- an unsigned big-endian whole byte integer.
99 uintle -- an unsigned little-endian whole byte integer.
100 uintne -- an unsigned native-endian whole byte integer.
101 filename -- the path of a file which will be opened in binary read-only mode.
103 Other keyword arguments:
104 length -- length of the bitstring in bits, if needed and appropriate.
105 It must be supplied for all integer and float initialisers.
106 offset -- bit offset to the data. These offset bits are
107 ignored and this is mainly intended for use when
108 initialising using 'bytes' or 'filename'.
110 """
111 self._bitstore.immutable = True
113 def __new__(cls: Type[TBits], auto: Optional[Union[BitsType, int]] = None, /, length: Optional[int] = None,
114 offset: Optional[int] = None, pos: Optional[int] = None, **kwargs) -> TBits:
115 x = super().__new__(cls)
116 if auto is None and not kwargs:
117 # No initialiser so fill with zero bits up to length
118 if length is not None:
119 x._bitstore = BitStore(length)
120 x._bitstore.setall(0)
121 else:
122 x._bitstore = BitStore()
123 return x
124 x._initialise(auto, length, offset, **kwargs)
125 return x
127 @classmethod
128 def _create_from_bitstype(cls: Type[TBits], auto: BitsType, /) -> TBits:
129 if isinstance(auto, Bits):
130 return auto
131 b = super().__new__(cls)
132 b._setauto_no_length_or_offset(auto)
133 return b
135 def _initialise(self, auto: Any, /, length: Optional[int], offset: Optional[int], **kwargs) -> None:
136 if auto is not None:
137 if isinstance(auto, numbers.Integral):
138 # Initialise with s zero bits.
139 if auto < 0:
140 raise bitstring.CreationError(f"Can't create bitstring of negative length {auto}.")
141 self._bitstore = BitStore(int(auto))
142 self._bitstore.setall(0)
143 return
144 self._setauto(auto, length, offset)
145 return
146 k, v = kwargs.popitem()
147 if k == 'bytes':
148 # Special case for bytes as we want to allow offsets and lengths to work only on creation.
149 self._setbytes_with_truncation(v, length, offset)
150 return
151 if k == 'filename':
152 self._setfile(v, length, offset)
153 return
154 if k == 'bitarray':
155 self._setbitarray(v, length, offset)
156 return
157 if k == 'auto':
158 raise bitstring.CreationError(
159 f"The 'auto' parameter should not be given explicitly - just use the first positional argument. "
160 f"Instead of '{self.__class__.__name__}(auto=x)' use '{self.__class__.__name__}(x)'.")
161 if offset is not None:
162 raise bitstring.CreationError("offset cannot be used when initialising with '{k}'.")
163 try:
164 Dtype(k, length).set_fn(self, v)
165 except ValueError as e:
166 raise bitstring.CreationError(e)
168 def __getattr__(self, attribute: str) -> Any:
169 # Support for arbitrary attributes like u16 or f64.
170 try:
171 d = Dtype(attribute)
172 except ValueError:
173 raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attribute}'.")
174 if d.bitlength is not None and len(self) != d.bitlength:
175 raise ValueError(f"bitstring length {len(self)} doesn't match length {d.bitlength} of property '{attribute}'.")
176 return d.read_fn(self, 0)
178 def __iter__(self) -> Iterable[bool]:
179 return iter(self._bitstore)
181 def __copy__(self: TBits) -> TBits:
182 """Return a new copy of the Bits for the copy module."""
183 # Note that if you want a new copy (different ID), use _copy instead.
184 # The copy can return self as it's immutable.
185 return self
187 def __lt__(self, other: Any) -> bool:
188 # bitstrings can't really be ordered.
189 return NotImplemented
191 def __gt__(self, other: Any) -> bool:
192 return NotImplemented
194 def __le__(self, other: Any) -> bool:
195 return NotImplemented
197 def __ge__(self, other: Any) -> bool:
198 return NotImplemented
200 def __add__(self: TBits, bs: BitsType) -> TBits:
201 """Concatenate bitstrings and return new bitstring.
203 bs -- the bitstring to append.
205 """
206 bs = self.__class__._create_from_bitstype(bs)
207 s = self._copy() if len(bs) <= len(self) else bs._copy()
208 if len(bs) <= len(self):
209 s._addright(bs)
210 else:
211 s._addleft(self)
212 return s
214 def __radd__(self: TBits, bs: BitsType) -> TBits:
215 """Append current bitstring to bs and return new bitstring.
217 bs -- An object that can be 'auto' initialised as a bitstring that will be appended to.
219 """
220 bs = self.__class__._create_from_bitstype(bs)
221 return bs.__add__(self)
223 @overload
224 def __getitem__(self: TBits, key: slice, /) -> TBits:
225 ...
227 @overload
228 def __getitem__(self, key: int, /) -> bool:
229 ...
231 def __getitem__(self: TBits, key: Union[slice, int], /) -> Union[TBits, bool]:
232 """Return a new bitstring representing a slice of the current bitstring.
234 Indices are in units of the step parameter (default 1 bit).
235 Stepping is used to specify the number of bits in each item.
237 >>> print(BitArray('0b00110')[1:4])
238 '0b011'
239 >>> print(BitArray('0x00112233')[1:3:8])
240 '0x1122'
242 """
243 if isinstance(key, numbers.Integral):
244 return bool(self._bitstore.getindex(key))
245 bs = super().__new__(self.__class__)
246 bs._bitstore = self._bitstore.getslice_withstep(key)
247 return bs
249 def __len__(self) -> int:
250 """Return the length of the bitstring in bits."""
251 return self._getlength()
253 def __bytes__(self) -> bytes:
254 return self.tobytes()
256 def __str__(self) -> str:
257 """Return approximate string representation of bitstring for printing.
259 Short strings will be given wholly in hexadecimal or binary. Longer
260 strings may be part hexadecimal and part binary. Very long strings will
261 be truncated with '...'.
263 """
264 length = len(self)
265 if not length:
266 return ''
267 if length > MAX_CHARS * 4:
268 # Too long for hex. Truncate...
269 return ''.join(('0x', self[0:MAX_CHARS*4]._gethex(), '...'))
270 # If it's quite short and we can't do hex then use bin
271 if length < 32 and length % 4 != 0:
272 return '0b' + self.bin
273 # If we can use hex then do so
274 if not length % 4:
275 return '0x' + self.hex
276 # Otherwise first we do as much as we can in hex
277 # then add on 1, 2 or 3 bits on at the end
278 bits_at_end = length % 4
279 return ''.join(('0x', self[0:length - bits_at_end]._gethex(),
280 ', ', '0b', self[length - bits_at_end:]._getbin()))
282 def _repr(self, classname: str, length: int, pos: int):
283 pos_string = f', pos={pos}' if pos else ''
284 if hasattr(self, '_filename') and self._filename:
285 return f"{classname}(filename={self._filename!r}, length={length}{pos_string})"
286 else:
287 s = self.__str__()
288 lengthstring = ''
289 if s.endswith('...'):
290 lengthstring = f' # length={length}'
291 return f"{classname}('{s}'{pos_string}){lengthstring}"
293 def __repr__(self) -> str:
294 """Return representation that could be used to recreate the bitstring.
296 If the returned string is too long it will be truncated. See __str__().
298 """
299 return self._repr(self.__class__.__name__, len(self), 0)
301 def __eq__(self, bs: Any, /) -> bool:
302 """Return True if two bitstrings have the same binary representation.
304 >>> BitArray('0b1110') == '0xe'
305 True
307 """
308 try:
309 return self._bitstore == Bits._create_from_bitstype(bs)._bitstore
310 except TypeError:
311 return False
313 def __ne__(self, bs: Any, /) -> bool:
314 """Return False if two bitstrings have the same binary representation.
316 >>> BitArray('0b111') == '0x7'
317 False
319 """
320 return not self.__eq__(bs)
322 def __invert__(self: TBits) -> TBits:
323 """Return bitstring with every bit inverted.
325 Raises Error if the bitstring is empty.
327 """
328 if len(self) == 0:
329 raise bitstring.Error("Cannot invert empty bitstring.")
330 s = self._copy()
331 s._invert_all()
332 return s
334 def __lshift__(self: TBits, n: int, /) -> TBits:
335 """Return bitstring with bits shifted by n to the left.
337 n -- the number of bits to shift. Must be >= 0.
339 """
340 if n < 0:
341 raise ValueError("Cannot shift by a negative amount.")
342 if len(self) == 0:
343 raise ValueError("Cannot shift an empty bitstring.")
344 n = min(n, len(self))
345 s = self._absolute_slice(n, len(self))
346 s._addright(Bits(n))
347 return s
349 def __rshift__(self: TBits, n: int, /) -> TBits:
350 """Return bitstring with bits shifted by n to the right.
352 n -- the number of bits to shift. Must be >= 0.
354 """
355 if n < 0:
356 raise ValueError("Cannot shift by a negative amount.")
357 if len(self) == 0:
358 raise ValueError("Cannot shift an empty bitstring.")
359 if not n:
360 return self._copy()
361 s = self.__class__(length=min(n, len(self)))
362 n = min(n, len(self))
363 s._addright(self._absolute_slice(0, len(self) - n))
364 return s
366 def __mul__(self: TBits, n: int, /) -> TBits:
367 """Return bitstring consisting of n concatenations of self.
369 Called for expression of the form 'a = b*3'.
370 n -- The number of concatenations. Must be >= 0.
372 """
373 if n < 0:
374 raise ValueError("Cannot multiply by a negative integer.")
375 if not n:
376 return self.__class__()
377 s = self._copy()
378 s._imul(n)
379 return s
381 def __rmul__(self: TBits, n: int, /) -> TBits:
382 """Return bitstring consisting of n concatenations of self.
384 Called for expressions of the form 'a = 3*b'.
385 n -- The number of concatenations. Must be >= 0.
387 """
388 return self.__mul__(n)
390 def __and__(self: TBits, bs: BitsType, /) -> TBits:
391 """Bit-wise 'and' between two bitstrings. Returns new bitstring.
393 bs -- The bitstring to '&' with.
395 Raises ValueError if the two bitstrings have differing lengths.
397 """
398 if bs is self:
399 return self.copy()
400 bs = Bits._create_from_bitstype(bs)
401 s = object.__new__(self.__class__)
402 s._bitstore = self._bitstore & bs._bitstore
403 return s
405 def __rand__(self: TBits, bs: BitsType, /) -> TBits:
406 """Bit-wise 'and' between two bitstrings. Returns new bitstring.
408 bs -- the bitstring to '&' with.
410 Raises ValueError if the two bitstrings have differing lengths.
412 """
413 return self.__and__(bs)
415 def __or__(self: TBits, bs: BitsType, /) -> TBits:
416 """Bit-wise 'or' between two bitstrings. Returns new bitstring.
418 bs -- The bitstring to '|' with.
420 Raises ValueError if the two bitstrings have differing lengths.
422 """
423 if bs is self:
424 return self.copy()
425 bs = Bits._create_from_bitstype(bs)
426 s = object.__new__(self.__class__)
427 s._bitstore = self._bitstore | bs._bitstore
428 return s
430 def __ror__(self: TBits, bs: BitsType, /) -> TBits:
431 """Bit-wise 'or' between two bitstrings. Returns new bitstring.
433 bs -- The bitstring to '|' with.
435 Raises ValueError if the two bitstrings have differing lengths.
437 """
438 return self.__or__(bs)
440 def __xor__(self: TBits, bs: BitsType, /) -> TBits:
441 """Bit-wise 'xor' between two bitstrings. Returns new bitstring.
443 bs -- The bitstring to '^' with.
445 Raises ValueError if the two bitstrings have differing lengths.
447 """
448 bs = Bits._create_from_bitstype(bs)
449 s = object.__new__(self.__class__)
450 s._bitstore = self._bitstore ^ bs._bitstore
451 return s
453 def __rxor__(self: TBits, bs: BitsType, /) -> TBits:
454 """Bit-wise 'xor' between two bitstrings. Returns new bitstring.
456 bs -- The bitstring to '^' with.
458 Raises ValueError if the two bitstrings have differing lengths.
460 """
461 return self.__xor__(bs)
463 def __contains__(self, bs: BitsType, /) -> bool:
464 """Return whether bs is contained in the current bitstring.
466 bs -- The bitstring to search for.
468 """
469 found = Bits.find(self, bs, bytealigned=False)
470 return bool(found)
472 def __hash__(self) -> int:
473 """Return an integer hash of the object."""
474 # Only requirement is that equal bitstring should return the same hash.
475 # For equal bitstrings the bytes at the start/end will be the same and they will have the same length
476 # (need to check the length as there could be zero padding when getting the bytes). We do not check any
477 # bit position inside the bitstring as that does not feature in the __eq__ operation.
478 if len(self) <= 2000:
479 # Use the whole bitstring.
480 return hash((self.tobytes(), len(self)))
481 else:
482 # We can't in general hash the whole bitstring (it could take hours!)
483 # So instead take some bits from the start and end.
484 return hash(((self[:800] + self[-800:]).tobytes(), len(self)))
486 def __bool__(self) -> bool:
487 """Return False if bitstring is empty, otherwise return True."""
488 return len(self) != 0
490 def _clear(self) -> None:
491 """Reset the bitstring to an empty state."""
492 self._bitstore = BitStore()
494 def _setauto_no_length_or_offset(self, s: BitsType, /) -> None:
495 """Set bitstring from a bitstring, file, bool, array, iterable or string."""
496 if isinstance(s, str):
497 self._bitstore = bitstore_helpers.str_to_bitstore(s)
498 elif isinstance(s, Bits):
499 self._bitstore = s._bitstore.copy()
500 elif isinstance(s, (bytes, bytearray, memoryview)):
501 self._bitstore = BitStore.frombytes(bytearray(s))
502 elif isinstance(s, io.BytesIO):
503 self._bitstore = BitStore.frombytes(s.getvalue())
504 elif isinstance(s, io.BufferedReader):
505 self._setfile(s.name)
506 elif isinstance(s, bitarray.bitarray):
507 self._bitstore = BitStore(s)
508 elif isinstance(s, array.array):
509 self._bitstore = BitStore.frombytes(s.tobytes())
510 elif isinstance(s, abc.Iterable):
511 # Evaluate each item as True or False and set bits to 1 or 0.
512 self._setbin_unsafe(''.join(str(int(bool(x))) for x in s))
513 elif isinstance(s, numbers.Integral):
514 raise TypeError(f"It's no longer possible to auto initialise a bitstring from an integer."
515 f" Use '{self.__class__.__name__}({s})' instead of just '{s}' as this makes it "
516 f"clearer that a bitstring of {int(s)} zero bits will be created.")
517 else:
518 raise TypeError(f"Cannot initialise bitstring from type '{type(s)}'.")
520 def _setauto(self, s: BitsType, length: Optional[int], offset: Optional[int], /) -> None:
521 """Set bitstring from a bitstring, file, bool, array, iterable or string."""
522 # As s can be so many different things it's important to do the checks
523 # in the correct order, as some types are also other allowed types.
524 if offset is None and length is None:
525 return self._setauto_no_length_or_offset(s)
526 if offset is None:
527 offset = 0
529 if isinstance(s, io.BytesIO):
530 if length is None:
531 length = s.seek(0, 2) * 8 - offset
532 byteoffset, offset = divmod(offset, 8)
533 bytelength = (length + byteoffset * 8 + offset + 7) // 8 - byteoffset
534 if length + byteoffset * 8 + offset > s.seek(0, 2) * 8:
535 raise bitstring.CreationError("BytesIO object is not long enough for specified length and offset.")
536 self._bitstore = BitStore.frombytes(s.getvalue()[byteoffset: byteoffset + bytelength]).getslice(
537 offset, offset + length)
538 return
540 if isinstance(s, io.BufferedReader):
541 self._setfile(s.name, length, offset)
542 return
544 if isinstance(s, (str, Bits, bytes, bytearray, memoryview, io.BytesIO, io.BufferedReader,
545 bitarray.bitarray, array.array, abc.Iterable)):
546 raise bitstring.CreationError(f"Cannot initialise bitstring from type '{type(s)}' when using explicit lengths or offsets.")
547 raise TypeError(f"Cannot initialise bitstring from type '{type(s)}'.")
549 def _setfile(self, filename: str, length: Optional[int] = None, offset: Optional[int] = None) -> None:
550 """Use file as source of bits."""
551 with open(pathlib.Path(filename), 'rb') as source:
552 if offset is None:
553 offset = 0
554 m = mmap.mmap(source.fileno(), 0, access=mmap.ACCESS_READ)
555 if offset == 0:
556 self._filename = source.name
557 self._bitstore = BitStore.frombuffer(m, length=length)
558 else:
559 # If offset is given then always read into memory.
560 temp = BitStore.frombuffer(m)
561 if length is None:
562 if offset > len(temp):
563 raise bitstring.CreationError(f"The offset of {offset} bits is greater than the file length ({len(temp)} bits).")
564 self._bitstore = temp.getslice(offset, None)
565 else:
566 self._bitstore = temp.getslice(offset, offset + length)
567 if len(self) != length:
568 raise bitstring.CreationError(f"Can't use a length of {length} bits and an offset of {offset} bits as file length is only {len(temp)} bits.")
570 def _setbitarray(self, ba: bitarray.bitarray, length: Optional[int], offset: Optional[int]) -> None:
571 if offset is None:
572 offset = 0
573 if offset > len(ba):
574 raise bitstring.CreationError(f"Offset of {offset} too large for bitarray of length {len(ba)}.")
575 if length is None:
576 self._bitstore = BitStore(ba[offset:])
577 else:
578 if offset + length > len(ba):
579 raise bitstring.CreationError(
580 f"Offset of {offset} and length of {length} too large for bitarray of length {len(ba)}.")
581 self._bitstore = BitStore(ba[offset: offset + length])
583 def _setbits(self, bs: BitsType, length: None = None) -> None:
584 bs = Bits._create_from_bitstype(bs)
585 self._bitstore = bs._bitstore
587 def _setp3binary(self, f: float) -> None:
588 self._bitstore = bitstore_helpers.p3binary2bitstore(f)
590 def _setp4binary(self, f: float) -> None:
591 self._bitstore = bitstore_helpers.p4binary2bitstore(f)
593 def _sete4m3mxfp(self, f: float) -> None:
594 self._bitstore = bitstore_helpers.e4m3mxfp2bitstore(f)
596 def _sete5m2mxfp(self, f: float) -> None:
597 self._bitstore = bitstore_helpers.e5m2mxfp2bitstore(f)
599 def _sete3m2mxfp(self, f: float) -> None:
600 self._bitstore = bitstore_helpers.e3m2mxfp2bitstore(f)
602 def _sete2m3mxfp(self, f: float) -> None:
603 self._bitstore = bitstore_helpers.e2m3mxfp2bitstore(f)
605 def _sete2m1mxfp(self, f: float) -> None:
606 self._bitstore = bitstore_helpers.e2m1mxfp2bitstore(f)
608 def _sete8m0mxfp(self, f: float) -> None:
609 self._bitstore = bitstore_helpers.e8m0mxfp2bitstore(f)
611 def _setmxint(self, f: float) -> None:
612 self._bitstore = bitstore_helpers.mxint2bitstore(f)
614 def _setbytes(self, data: Union[bytearray, bytes, List], length:None = None) -> None:
615 """Set the data from a bytes or bytearray object."""
616 self._bitstore = BitStore.frombytes(bytes(data))
618 def _setbytes_with_truncation(self, data: Union[bytearray, bytes], length: Optional[int] = None, offset: Optional[int] = None) -> None:
619 """Set the data from a bytes or bytearray object, with optional offset and length truncations."""
620 if offset is None and length is None:
621 return self._setbytes(data)
622 data = bytearray(data)
623 if offset is None:
624 offset = 0
625 if length is None:
626 # Use to the end of the data
627 length = len(data) * 8 - offset
628 else:
629 if length + offset > len(data) * 8:
630 raise bitstring.CreationError(f"Not enough data present. Need {length + offset} bits, have {len(data) * 8}.")
631 self._bitstore = BitStore.frombytes(data).getslice_msb0(offset, offset + length)
633 def _getbytes(self) -> bytes:
634 """Return the data as an ordinary bytes object."""
635 if len(self) % 8:
636 raise bitstring.InterpretError("Cannot interpret as bytes unambiguously - not multiple of 8 bits.")
637 return self._bitstore.tobytes()
639 _unprintable = list(range(0x00, 0x20)) # ASCII control characters
640 _unprintable.extend(range(0x7f, 0xff)) # DEL char + non-ASCII
642 def _getbytes_printable(self) -> str:
643 """Return an approximation of the data as a string of printable characters."""
644 bytes_ = self._getbytes()
645 # For everything that isn't printable ASCII, use value from 'Latin Extended-A' unicode block.
646 string = ''.join(chr(0x100 + x) if x in Bits._unprintable else chr(x) for x in bytes_)
647 return string
649 def _setuint(self, uint: int, length: Optional[int] = None) -> None:
650 """Reset the bitstring to have given unsigned int interpretation."""
651 # If no length given, and we've previously been given a length, use it.
652 if length is None and hasattr(self, 'len') and len(self) != 0:
653 length = len(self)
654 if length is None or length == 0:
655 raise bitstring.CreationError("A non-zero length must be specified with a uint initialiser.")
656 self._bitstore = bitstore_helpers.int2bitstore(uint, length, False)
658 def _getuint(self) -> int:
659 """Return data as an unsigned int."""
660 if len(self) == 0:
661 raise bitstring.InterpretError("Cannot interpret a zero length bitstring as an integer.")
662 return self._bitstore.slice_to_uint()
664 def _setint(self, int_: int, length: Optional[int] = None) -> None:
665 """Reset the bitstring to have given signed int interpretation."""
666 # If no length given, and we've previously been given a length, use it.
667 if length is None and hasattr(self, 'len') and len(self) != 0:
668 length = len(self)
669 if length is None or length == 0:
670 raise bitstring.CreationError("A non-zero length must be specified with an int initialiser.")
671 self._bitstore = bitstore_helpers.int2bitstore(int_, length, True)
673 def _getint(self) -> int:
674 """Return data as a two's complement signed int."""
675 if len(self) == 0:
676 raise bitstring.InterpretError("Cannot interpret bitstring without a length as an integer.")
677 return self._bitstore.slice_to_int()
679 def _setuintbe(self, uintbe: int, length: Optional[int] = None) -> None:
680 """Set the bitstring to a big-endian unsigned int interpretation."""
681 if length is None and hasattr(self, 'len') and len(self) != 0:
682 length = len(self)
683 if length is None or length == 0:
684 raise bitstring.CreationError("A non-zero length must be specified with a uintbe initialiser.")
685 self._bitstore = bitstore_helpers.int2bitstore(uintbe, length, False)
687 def _getuintbe(self) -> int:
688 """Return data as a big-endian two's complement unsigned int."""
689 if len(self) % 8:
690 raise bitstring.InterpretError(f"Big-endian integers must be whole-byte. Length = {len(self)} bits.")
691 return self._getuint()
693 def _setintbe(self, intbe: int, length: Optional[int] = None) -> None:
694 """Set bitstring to a big-endian signed int interpretation."""
695 if length is None and hasattr(self, 'len') and len(self) != 0:
696 length = len(self)
697 if length is None or length == 0:
698 raise bitstring.CreationError("A non-zero length must be specified with a intbe initialiser.")
699 self._bitstore = bitstore_helpers.int2bitstore(intbe, length, True)
701 def _getintbe(self) -> int:
702 """Return data as a big-endian two's complement signed int."""
703 if len(self) % 8:
704 raise bitstring.InterpretError(f"Big-endian integers must be whole-byte. Length = {len(self)} bits.")
705 return self._getint()
707 def _setuintle(self, uintle: int, length: Optional[int] = None) -> None:
708 if length is None and hasattr(self, 'len') and len(self) != 0:
709 length = len(self)
710 if length is None or length == 0:
711 raise bitstring.CreationError("A non-zero length must be specified with a uintle initialiser.")
712 self._bitstore = bitstore_helpers.intle2bitstore(uintle, length, False)
714 def _getuintle(self) -> int:
715 """Interpret as a little-endian unsigned int."""
716 if len(self) % 8:
717 raise bitstring.InterpretError(f"Little-endian integers must be whole-byte. Length = {len(self)} bits.")
718 bs = BitStore.frombytes(self._bitstore.tobytes()[::-1])
719 return bs.slice_to_uint()
721 def _setintle(self, intle: int, length: Optional[int] = None) -> None:
722 if length is None and hasattr(self, 'len') and len(self) != 0:
723 length = len(self)
724 if length is None or length == 0:
725 raise bitstring.CreationError("A non-zero length must be specified with an intle initialiser.")
726 self._bitstore = bitstore_helpers.intle2bitstore(intle, length, True)
728 def _getintle(self) -> int:
729 """Interpret as a little-endian signed int."""
730 if len(self) % 8:
731 raise bitstring.InterpretError(f"Little-endian integers must be whole-byte. Length = {len(self)} bits.")
732 bs = BitStore.frombytes(self._bitstore.tobytes()[::-1])
733 return bs.slice_to_int()
735 def _getp4binary(self) -> float:
736 u = self._getuint()
737 return p4binary_fmt.lut_binary8_to_float[u]
739 def _getp3binary(self) -> float:
740 u = self._getuint()
741 return p3binary_fmt.lut_binary8_to_float[u]
743 def _gete4m3mxfp(self) -> float:
744 u = self._getuint()
745 return e4m3mxfp_saturate_fmt.lut_int_to_float[u]
747 def _gete5m2mxfp(self) -> float:
748 u = self._getuint()
749 return e5m2mxfp_saturate_fmt.lut_int_to_float[u]
751 def _gete3m2mxfp(self) -> float:
752 u = self._getuint()
753 return e3m2mxfp_fmt.lut_int_to_float[u]
755 def _gete2m3mxfp(self) -> float:
756 u = self._getuint()
757 return e2m3mxfp_fmt.lut_int_to_float[u]
759 def _gete2m1mxfp(self) -> float:
760 u = self._getuint()
761 return e2m1mxfp_fmt.lut_int_to_float[u]
763 def _gete8m0mxfp(self) -> float:
764 u = self._getuint() - 127
765 if u == 128:
766 return float('nan')
767 return 2.0 ** u
769 def _getmxint(self) -> float:
770 u = self._getint()
771 return float(u) * 2 ** -6
774 def _setfloat(self, f: float, length: Optional[int], big_endian: bool) -> None:
775 if length is None and hasattr(self, 'len') and len(self) != 0:
776 length = len(self)
777 if length is None or length not in [16, 32, 64]:
778 raise bitstring.CreationError("A length of 16, 32, or 64 must be specified with a float initialiser.")
779 self._bitstore = bitstore_helpers.float2bitstore(f, length, big_endian)
781 def _setfloatbe(self, f: float, length: Optional[int] = None) -> None:
782 self._setfloat(f, length, True)
784 def _getfloatbe(self) -> float:
785 """Interpret the whole bitstring as a big-endian float."""
786 fmt = {16: '>e', 32: '>f', 64: '>d'}[len(self)]
787 return struct.unpack(fmt, self._bitstore.tobytes())[0]
789 def _setfloatle(self, f: float, length: Optional[int] = None) -> None:
790 self._setfloat(f, length, False)
792 def _getfloatle(self) -> float:
793 """Interpret the whole bitstring as a little-endian float."""
794 fmt = {16: '<e', 32: '<f', 64: '<d'}[len(self)]
795 return struct.unpack(fmt, self._bitstore.tobytes())[0]
797 def _getbfloatbe(self) -> float:
798 zero_padded = self + Bits(16)
799 return zero_padded._getfloatbe()
801 def _setbfloatbe(self, f: Union[float, str], length: Optional[int] = None) -> None:
802 if length is not None and length != 16:
803 raise bitstring.CreationError(f"bfloats must be length 16, received a length of {length} bits.")
804 self._bitstore = bitstore_helpers.bfloat2bitstore(f, True)
806 def _getbfloatle(self) -> float:
807 zero_padded = Bits(16) + self
808 return zero_padded._getfloatle()
810 def _setbfloatle(self, f: Union[float, str], length: Optional[int] = None) -> None:
811 if length is not None and length != 16:
812 raise bitstring.CreationError(f"bfloats must be length 16, received a length of {length} bits.")
813 self._bitstore = bitstore_helpers.bfloat2bitstore(f, False)
815 def _setue(self, i: int) -> None:
816 """Initialise bitstring with unsigned exponential-Golomb code for integer i.
818 Raises CreationError if i < 0.
820 """
821 if bitstring.options.lsb0:
822 raise bitstring.CreationError("Exp-Golomb codes cannot be used in lsb0 mode.")
823 self._bitstore = bitstore_helpers.ue2bitstore(i)
825 def _readue(self, pos: int) -> Tuple[int, int]:
826 """Return interpretation of next bits as unsigned exponential-Golomb code.
828 Raises ReadError if the end of the bitstring is encountered while
829 reading the code.
831 """
832 if bitstring.options.lsb0:
833 raise bitstring.ReadError("Exp-Golomb codes cannot be read in lsb0 mode.")
834 oldpos = pos
835 try:
836 while not self[pos]:
837 pos += 1
838 except IndexError:
839 raise bitstring.ReadError("Read off end of bitstring trying to read code.")
840 leadingzeros = pos - oldpos
841 codenum = (1 << leadingzeros) - 1
842 if leadingzeros > 0:
843 if pos + leadingzeros + 1 > len(self):
844 raise bitstring.ReadError("Read off end of bitstring trying to read code.")
845 codenum += self[pos + 1:pos + 1 + leadingzeros]._getuint()
846 pos += leadingzeros + 1
847 else:
848 assert codenum == 0
849 pos += 1
850 return codenum, pos
852 def _getue(self) -> Tuple[int, int]:
853 try:
854 return self._readue(0)
855 except bitstring.ReadError:
856 raise bitstring.InterpretError
858 def _getse(self) -> Tuple[int, int]:
859 try:
860 return self._readse(0)
861 except bitstring.ReadError:
862 raise bitstring.InterpretError
864 def _getuie(self) -> Tuple[int, int]:
865 try:
866 return self._readuie(0)
867 except bitstring.ReadError:
868 raise bitstring.InterpretError
870 def _getsie(self) -> Tuple[int, int]:
871 try:
872 return self._readsie(0)
873 except bitstring.ReadError:
874 raise bitstring.InterpretError
876 def _setse(self, i: int) -> None:
877 """Initialise bitstring with signed exponential-Golomb code for integer i."""
878 if bitstring.options.lsb0:
879 raise bitstring.CreationError("Exp-Golomb codes cannot be used in lsb0 mode.")
880 self._bitstore = bitstore_helpers.se2bitstore(i)
882 def _readse(self, pos: int) -> Tuple[int, int]:
883 """Return interpretation of next bits as a signed exponential-Golomb code.
885 Advances position to after the read code.
887 Raises ReadError if the end of the bitstring is encountered while
888 reading the code.
890 """
891 codenum, pos = self._readue(pos)
892 m = (codenum + 1) // 2
893 return (m, pos) if codenum % 2 else (-m, pos)
895 def _setuie(self, i: int) -> None:
896 """Initialise bitstring with unsigned interleaved exponential-Golomb code for integer i.
898 Raises CreationError if i < 0.
900 """
901 if bitstring.options.lsb0:
902 raise bitstring.CreationError("Exp-Golomb codes cannot be used in lsb0 mode.")
903 self._bitstore = bitstore_helpers.uie2bitstore(i)
905 def _readuie(self, pos: int) -> Tuple[int, int]:
906 """Return interpretation of next bits as unsigned interleaved exponential-Golomb code.
908 Raises ReadError if the end of the bitstring is encountered while
909 reading the code.
911 """
912 if bitstring.options.lsb0:
913 raise bitstring.ReadError("Exp-Golomb codes cannot be read in lsb0 mode.")
914 try:
915 codenum: int = 1
916 while not self[pos]:
917 pos += 1
918 codenum <<= 1
919 codenum += self[pos]
920 pos += 1
921 pos += 1
922 except IndexError:
923 raise bitstring.ReadError("Read off end of bitstring trying to read code.")
924 return codenum - 1, pos
926 def _setsie(self, i: int, ) -> None:
927 """Initialise bitstring with signed interleaved exponential-Golomb code for integer i."""
928 if bitstring.options.lsb0:
929 raise bitstring.CreationError("Exp-Golomb codes cannot be used in lsb0 mode.")
930 self._bitstore = bitstore_helpers.sie2bitstore(i)
932 def _readsie(self, pos: int) -> Tuple[int, int]:
933 """Return interpretation of next bits as a signed interleaved exponential-Golomb code.
935 Advances position to after the read code.
937 Raises ReadError if the end of the bitstring is encountered while
938 reading the code.
940 """
941 codenum, pos = self._readuie(pos)
942 if not codenum:
943 return 0, pos
944 try:
945 return (-codenum, pos + 1) if self[pos] else (codenum, pos + 1)
946 except IndexError:
947 raise bitstring.ReadError("Read off end of bitstring trying to read code.")
949 def _setbool(self, value: Union[bool, str]) -> None:
950 # We deliberately don't want to have implicit conversions to bool here.
951 # If we did then it would be difficult to deal with the 'False' string.
952 if value in (1, 'True', '1'):
953 self._bitstore = BitStore('1')
954 elif value in (0, 'False', '0'):
955 self._bitstore = BitStore('0')
956 else:
957 raise bitstring.CreationError(f"Cannot initialise boolean with {value}.")
959 def _getbool(self) -> bool:
960 return self[0]
962 def _getpad(self) -> None:
963 return None
965 def _setpad(self, value: None, length: int) -> None:
966 self._bitstore = BitStore(length)
968 def _setbin_safe(self, binstring: str, length: None = None) -> None:
969 """Reset the bitstring to the value given in binstring."""
970 self._bitstore = bitstore_helpers.bin2bitstore(binstring)
972 def _setbin_unsafe(self, binstring: str, length: None = None) -> None:
973 """Same as _setbin_safe, but input isn't sanity checked. binstring mustn't start with '0b'."""
974 self._bitstore = bitstore_helpers.bin2bitstore_unsafe(binstring)
976 def _getbin(self) -> str:
977 """Return interpretation as a binary string."""
978 return self._bitstore.slice_to_bin()
980 def _setoct(self, octstring: str, length: None = None) -> None:
981 """Reset the bitstring to have the value given in octstring."""
982 self._bitstore = bitstore_helpers.oct2bitstore(octstring)
984 def _getoct(self) -> str:
985 """Return interpretation as an octal string."""
986 return self._bitstore.slice_to_oct()
988 def _sethex(self, hexstring: str, length: None = None) -> None:
989 """Reset the bitstring to have the value given in hexstring."""
990 self._bitstore = bitstore_helpers.hex2bitstore(hexstring)
992 def _gethex(self) -> str:
993 """Return the hexadecimal representation as a string.
995 Raises an InterpretError if the bitstring's length is not a multiple of 4.
997 """
998 return self._bitstore.slice_to_hex()
1000 def _getlength(self) -> int:
1001 """Return the length of the bitstring in bits."""
1002 return len(self._bitstore)
1004 def _copy(self: TBits) -> TBits:
1005 """Create and return a new copy of the Bits (always in memory)."""
1006 # Note that __copy__ may choose to return self if it's immutable. This method always makes a copy.
1007 s_copy = self.__class__()
1008 s_copy._bitstore = self._bitstore._copy()
1009 return s_copy
1011 def _slice(self: TBits, start: int, end: int) -> TBits:
1012 """Used internally to get a slice, without error checking."""
1013 bs = self.__class__()
1014 bs._bitstore = self._bitstore.getslice(start, end)
1015 return bs
1017 def _absolute_slice(self: TBits, start: int, end: int) -> TBits:
1018 """Used internally to get a slice, without error checking.
1019 Uses MSB0 bit numbering even if LSB0 is set."""
1020 if end == start:
1021 return self.__class__()
1022 assert start < end, f"start={start}, end={end}"
1023 bs = self.__class__()
1024 bs._bitstore = self._bitstore.getslice_msb0(start, end)
1025 return bs
1027 def _readtoken(self, name: str, pos: int, length: Optional[int]) -> Tuple[Union[float, int, str, None, Bits], int]:
1028 """Reads a token from the bitstring and returns the result."""
1029 dtype = dtype_register.get_dtype(name, length)
1030 if dtype.bitlength is not None and dtype.bitlength > len(self) - pos:
1031 raise bitstring.ReadError("Reading off the end of the data. "
1032 f"Tried to read {dtype.bitlength} bits when only {len(self) - pos} available.")
1033 try:
1034 val = dtype.read_fn(self, pos)
1035 if isinstance(val, tuple):
1036 return val
1037 else:
1038 assert length is not None
1039 return val, pos + dtype.bitlength
1040 except KeyError:
1041 raise ValueError(f"Can't parse token {name}:{length}")
1043 def _addright(self, bs: Bits, /) -> None:
1044 """Add a bitstring to the RHS of the current bitstring."""
1045 self._bitstore += bs._bitstore
1047 def _addleft(self, bs: Bits, /) -> None:
1048 """Prepend a bitstring to the current bitstring."""
1049 if bs._bitstore.immutable:
1050 self._bitstore = bs._bitstore._copy() + self._bitstore
1051 else:
1052 self._bitstore = bs._bitstore + self._bitstore
1054 def _truncateleft(self: TBits, bits: int, /) -> TBits:
1055 """Truncate bits from the start of the bitstring. Return the truncated bits."""
1056 assert 0 <= bits <= len(self)
1057 if bits == 0:
1058 return self.__class__()
1059 truncated_bits = self._absolute_slice(0, bits)
1060 if bits == len(self):
1061 self._clear()
1062 return truncated_bits
1063 self._bitstore = self._bitstore.getslice_msb0(bits, None)
1064 return truncated_bits
1066 def _truncateright(self: TBits, bits: int, /) -> TBits:
1067 """Truncate bits from the end of the bitstring. Return the truncated bits."""
1068 assert 0 <= bits <= len(self)
1069 if bits == 0:
1070 return self.__class__()
1071 truncated_bits = self._absolute_slice(len(self) - bits, len(self))
1072 if bits == len(self):
1073 self._clear()
1074 return truncated_bits
1075 self._bitstore = self._bitstore.getslice_msb0(None, -bits)
1076 return truncated_bits
1078 def _insert(self, bs: Bits, pos: int, /) -> None:
1079 """Insert bs at pos."""
1080 assert 0 <= pos <= len(self)
1081 self._bitstore[pos: pos] = bs._bitstore
1082 return
1084 def _overwrite(self, bs: Bits, pos: int, /) -> None:
1085 """Overwrite with bs at pos."""
1086 assert 0 <= pos <= len(self)
1087 if bs is self:
1088 # Just overwriting with self, so do nothing.
1089 assert pos == 0
1090 return
1091 self._bitstore[pos: pos + len(bs)] = bs._bitstore
1093 def _delete(self, bits: int, pos: int, /) -> None:
1094 """Delete bits at pos."""
1095 assert 0 <= pos <= len(self)
1096 assert pos + bits <= len(self), f"pos={pos}, bits={bits}, len={len(self)}"
1097 del self._bitstore[pos: pos + bits]
1098 return
1100 def _reversebytes(self, start: int, end: int) -> None:
1101 """Reverse bytes in-place."""
1102 assert (end - start) % 8 == 0
1103 self._bitstore[start:end] = BitStore.frombytes(self._bitstore.getslice(start, end).tobytes()[::-1])
1105 def _invert(self, pos: int, /) -> None:
1106 """Flip bit at pos 1<->0."""
1107 assert 0 <= pos < len(self)
1108 self._bitstore.invert(pos)
1110 def _invert_all(self) -> None:
1111 """Invert every bit."""
1112 self._bitstore.invert()
1114 def _ilshift(self: TBits, n: int, /) -> TBits:
1115 """Shift bits by n to the left in place. Return self."""
1116 assert 0 < n <= len(self)
1117 self._addright(Bits(n))
1118 self._truncateleft(n)
1119 return self
1121 def _irshift(self: TBits, n: int, /) -> TBits:
1122 """Shift bits by n to the right in place. Return self."""
1123 assert 0 < n <= len(self)
1124 self._addleft(Bits(n))
1125 self._truncateright(n)
1126 return self
1128 def _imul(self: TBits, n: int, /) -> TBits:
1129 """Concatenate n copies of self in place. Return self."""
1130 assert n >= 0
1131 if n == 0:
1132 self._clear()
1133 else:
1134 m = 1
1135 old_len = len(self)
1136 while m * 2 < n:
1137 self._addright(self)
1138 m *= 2
1139 self._addright(self[0:(n - m) * old_len])
1140 return self
1142 def _getbits(self: TBits):
1143 return self._copy()
1145 def _validate_slice(self, start: Optional[int], end: Optional[int]) -> Tuple[int, int]:
1146 """Validate start and end and return them as positive bit positions."""
1147 start = 0 if start is None else (start + len(self) if start < 0 else start)
1148 end = len(self) if end is None else (end + len(self) if end < 0 else end)
1149 if not 0 <= start <= end <= len(self):
1150 raise ValueError(f"Invalid slice positions for bitstring length {len(self)}: start={start}, end={end}.")
1151 return start, end
1153 def unpack(self, fmt: Union[str, List[Union[str, int]]], **kwargs) -> List[Union[int, float, str, Bits, bool, bytes, None]]:
1154 """Interpret the whole bitstring using fmt and return list.
1156 fmt -- A single string or a list of strings with comma separated tokens
1157 describing how to interpret the bits in the bitstring. Items
1158 can also be integers, for reading new bitstring of the given length.
1159 kwargs -- A dictionary or keyword-value pairs - the keywords used in the
1160 format string will be replaced with their given value.
1162 Raises ValueError if the format is not understood. If not enough bits
1163 are available then all bits to the end of the bitstring will be used.
1165 See the docstring for 'read' for token examples.
1167 """
1168 return self._readlist(fmt, 0, **kwargs)[0]
1170 def _readlist(self, fmt: Union[str, List[Union[str, int, Dtype]]], pos: int, **kwargs) \
1171 -> Tuple[List[Union[int, float, str, Bits, bool, bytes, None]], int]:
1172 if isinstance(fmt, str):
1173 fmt = [fmt]
1174 # Convert to a flat list of Dtypes
1175 dtype_list = []
1176 for f_item in fmt:
1177 if isinstance(f_item, numbers.Integral):
1178 dtype_list.append(Dtype('bits', f_item))
1179 elif isinstance(f_item, Dtype):
1180 dtype_list.append(f_item)
1181 else:
1182 token_list = utils.preprocess_tokens(f_item)
1183 for t in token_list:
1184 try:
1185 name, length = utils.parse_name_length_token(t, **kwargs)
1186 except ValueError:
1187 dtype_list.append(Dtype('bits', int(t)))
1188 else:
1189 dtype_list.append(Dtype(name, length))
1190 return self._read_dtype_list(dtype_list, pos)
1192 def _read_dtype_list(self, dtypes: List[Dtype], pos: int) -> Tuple[List[Union[int, float, str, Bits, bool, bytes, None]], int]:
1193 has_stretchy_token = False
1194 bits_after_stretchy_token = 0
1195 for dtype in dtypes:
1196 stretchy = dtype.bitlength is None and not dtype.variable_length
1197 if stretchy:
1198 if has_stretchy_token:
1199 raise bitstring.Error("It's not possible to have more than one 'filler' token.")
1200 has_stretchy_token = True
1201 elif has_stretchy_token:
1202 if dtype.variable_length:
1203 raise bitstring.Error(f"It's not possible to parse a variable length token '{dtype}' after a 'filler' token.")
1204 bits_after_stretchy_token += dtype.bitlength
1206 # We should have precisely zero or one stretchy token
1207 vals = []
1208 for dtype in dtypes:
1209 stretchy = dtype.bitlength is None and not dtype.variable_length
1210 if stretchy:
1211 bits_remaining = len(self) - pos
1212 # Set length to the remaining bits
1213 bitlength = max(bits_remaining - bits_after_stretchy_token, 0)
1214 items, remainder = divmod(bitlength, dtype.bits_per_item)
1215 if remainder != 0:
1216 raise ValueError(
1217 f"The '{dtype.name}' type must have a bit length that is a multiple of {dtype.bits_per_item}"
1218 f" so cannot be created from the {bitlength} bits that are available for this stretchy token.")
1219 dtype = Dtype(dtype.name, items)
1220 if dtype.bitlength is not None:
1221 val = dtype.read_fn(self, pos)
1222 pos += dtype.bitlength
1223 else:
1224 val, pos = dtype.read_fn(self, pos)
1225 if val is not None: # Don't append pad tokens
1226 vals.append(val)
1227 return vals, pos
1229 def find(self, bs: BitsType, /, start: Optional[int] = None, end: Optional[int] = None,
1230 bytealigned: Optional[bool] = None) -> Union[Tuple[int], Tuple[()]]:
1231 """Find first occurrence of substring bs.
1233 Returns a single item tuple with the bit position if found, or an
1234 empty tuple if not found. The bit position (pos property) will
1235 also be set to the start of the substring if it is found.
1237 bs -- The bitstring to find.
1238 start -- The bit position to start the search. Defaults to 0.
1239 end -- The bit position one past the last bit to search.
1240 Defaults to len(self).
1241 bytealigned -- If True the bitstring will only be
1242 found on byte boundaries.
1244 Raises ValueError if bs is empty, if start < 0, if end > len(self) or
1245 if end < start.
1247 >>> BitArray('0xc3e').find('0b1111')
1248 (6,)
1250 """
1251 bs = Bits._create_from_bitstype(bs)
1252 if len(bs) == 0:
1253 raise ValueError("Cannot find an empty bitstring.")
1254 start, end = self._validate_slice(start, end)
1255 ba = bitstring.options.bytealigned if bytealigned is None else bytealigned
1256 p = self._find(bs, start, end, ba)
1257 return p
1259 def _find_lsb0(self, bs: Bits, start: int, end: int, bytealigned: bool) -> Union[Tuple[int], Tuple[()]]:
1260 # A forward find in lsb0 is very like a reverse find in msb0.
1261 assert start <= end
1262 assert bitstring.options.lsb0
1264 new_slice = bitstring.bitstore.offset_slice_indices_lsb0(slice(start, end, None), len(self))
1265 msb0_start, msb0_end = self._validate_slice(new_slice.start, new_slice.stop)
1266 p = self._rfind_msb0(bs, msb0_start, msb0_end, bytealigned)
1268 if p:
1269 return (len(self) - p[0] - len(bs),)
1270 else:
1271 return ()
1273 def _find_msb0(self, bs: Bits, start: int, end: int, bytealigned: bool) -> Union[Tuple[int], Tuple[()]]:
1274 """Find first occurrence of a binary string."""
1275 p = self._bitstore.find(bs._bitstore, start, end, bytealigned)
1276 return () if p == -1 else (p,)
1278 def findall(self, bs: BitsType, start: Optional[int] = None, end: Optional[int] = None, count: Optional[int] = None,
1279 bytealigned: Optional[bool] = None) -> Iterable[int]:
1280 """Find all occurrences of bs. Return generator of bit positions.
1282 bs -- The bitstring to find.
1283 start -- The bit position to start the search. Defaults to 0.
1284 end -- The bit position one past the last bit to search.
1285 Defaults to len(self).
1286 count -- The maximum number of occurrences to find.
1287 bytealigned -- If True the bitstring will only be found on
1288 byte boundaries.
1290 Raises ValueError if bs is empty, if start < 0, if end > len(self) or
1291 if end < start.
1293 Note that all occurrences of bs are found, even if they overlap.
1295 """
1296 if count is not None and count < 0:
1297 raise ValueError("In findall, count must be >= 0.")
1298 bs = Bits._create_from_bitstype(bs)
1299 start, end = self._validate_slice(start, end)
1300 ba = bitstring.options.bytealigned if bytealigned is None else bytealigned
1301 return self._findall(bs, start, end, count, ba)
1303 def _findall_msb0(self, bs: Bits, start: int, end: int, count: Optional[int],
1304 bytealigned: bool) -> Iterable[int]:
1305 c = 0
1306 for i in self._bitstore.findall_msb0(bs._bitstore, start, end, bytealigned):
1307 if count is not None and c >= count:
1308 return
1309 c += 1
1310 yield i
1311 return
1313 def _findall_lsb0(self, bs: Bits, start: int, end: int, count: Optional[int],
1314 bytealigned: bool) -> Iterable[int]:
1315 assert start <= end
1316 assert bitstring.options.lsb0
1318 new_slice = bitstring.bitstore.offset_slice_indices_lsb0(slice(start, end, None), len(self))
1319 msb0_start, msb0_end = self._validate_slice(new_slice.start, new_slice.stop)
1321 # Search chunks starting near the end and then moving back.
1322 c = 0
1323 increment = max(8192, len(bs) * 80)
1324 buffersize = min(increment + len(bs), msb0_end - msb0_start)
1325 pos = max(msb0_start, msb0_end - buffersize)
1326 while True:
1327 found = list(self._findall_msb0(bs, start=pos, end=pos + buffersize, count=None, bytealigned=False))
1328 if not found:
1329 if pos == msb0_start:
1330 return
1331 pos = max(msb0_start, pos - increment)
1332 continue
1333 while found:
1334 if count is not None and c >= count:
1335 return
1336 c += 1
1337 lsb0_pos = len(self) - found.pop() - len(bs)
1338 if not bytealigned or lsb0_pos % 8 == 0:
1339 yield lsb0_pos
1341 pos = max(msb0_start, pos - increment)
1342 if pos == msb0_start:
1343 return
1345 def rfind(self, bs: BitsType, /, start: Optional[int] = None, end: Optional[int] = None,
1346 bytealigned: Optional[bool] = None) -> Union[Tuple[int], Tuple[()]]:
1347 """Find final occurrence of substring bs.
1349 Returns a single item tuple with the bit position if found, or an
1350 empty tuple if not found. The bit position (pos property) will
1351 also be set to the start of the substring if it is found.
1353 bs -- The bitstring to find.
1354 start -- The bit position to end the reverse search. Defaults to 0.
1355 end -- The bit position one past the first bit to reverse search.
1356 Defaults to len(self).
1357 bytealigned -- If True the bitstring will only be found on byte
1358 boundaries.
1360 Raises ValueError if bs is empty, if start < 0, if end > len(self) or
1361 if end < start.
1363 """
1364 bs = Bits._create_from_bitstype(bs)
1365 start, end = self._validate_slice(start, end)
1366 ba = bitstring.options.bytealigned if bytealigned is None else bytealigned
1367 if len(bs) == 0:
1368 raise ValueError("Cannot find an empty bitstring.")
1369 p = self._rfind(bs, start, end, ba)
1370 return p
1372 def _rfind_msb0(self, bs: Bits, start: int, end: int, bytealigned: bool) -> Union[Tuple[int], Tuple[()]]:
1373 """Find final occurrence of a binary string."""
1374 p = self._bitstore.rfind(bs._bitstore, start, end, bytealigned)
1375 return () if p == -1 else (p,)
1377 def _rfind_lsb0(self, bs: Bits, start: int, end: int, bytealigned: bool) -> Union[Tuple[int], Tuple[()]]:
1378 # A reverse find in lsb0 is very like a forward find in msb0.
1379 assert start <= end
1380 assert bitstring.options.lsb0
1381 new_slice = bitstring.bitstore.offset_slice_indices_lsb0(slice(start, end, None), len(self))
1382 msb0_start, msb0_end = self._validate_slice(new_slice.start, new_slice.stop)
1384 p = self._find_msb0(bs, msb0_start, msb0_end, bytealigned)
1385 if p:
1386 return (len(self) - p[0] - len(bs),)
1387 else:
1388 return ()
1390 def cut(self, bits: int, start: Optional[int] = None, end: Optional[int] = None,
1391 count: Optional[int] = None) -> Iterator[Bits]:
1392 """Return bitstring generator by cutting into bits sized chunks.
1394 bits -- The size in bits of the bitstring chunks to generate.
1395 start -- The bit position to start the first cut. Defaults to 0.
1396 end -- The bit position one past the last bit to use in the cut.
1397 Defaults to len(self).
1398 count -- If specified then at most count items are generated.
1399 Default is to cut as many times as possible.
1401 """
1402 start_, end_ = self._validate_slice(start, end)
1403 if count is not None and count < 0:
1404 raise ValueError("Cannot cut - count must be >= 0.")
1405 if bits <= 0:
1406 raise ValueError("Cannot cut - bits must be >= 0.")
1407 c = 0
1408 while count is None or c < count:
1409 c += 1
1410 nextchunk = self._slice(start_, min(start_ + bits, end_))
1411 if len(nextchunk) == 0:
1412 return
1413 yield nextchunk
1414 if len(nextchunk) != bits:
1415 return
1416 start_ += bits
1417 return
1419 def split(self, delimiter: BitsType, start: Optional[int] = None, end: Optional[int] = None,
1420 count: Optional[int] = None, bytealigned: Optional[bool] = None) -> Iterable[Bits]:
1421 """Return bitstring generator by splitting using a delimiter.
1423 The first item returned is the initial bitstring before the delimiter,
1424 which may be an empty bitstring.
1426 delimiter -- The bitstring used as the divider.
1427 start -- The bit position to start the split. Defaults to 0.
1428 end -- The bit position one past the last bit to use in the split.
1429 Defaults to len(self).
1430 count -- If specified then at most count items are generated.
1431 Default is to split as many times as possible.
1432 bytealigned -- If True splits will only occur on byte boundaries.
1434 Raises ValueError if the delimiter is empty.
1436 """
1437 delimiter = Bits._create_from_bitstype(delimiter)
1438 if len(delimiter) == 0:
1439 raise ValueError("split delimiter cannot be empty.")
1440 start, end = self._validate_slice(start, end)
1441 bytealigned_: bool = bitstring.options.bytealigned if bytealigned is None else bytealigned
1442 if count is not None and count < 0:
1443 raise ValueError("Cannot split - count must be >= 0.")
1444 if count == 0:
1445 return
1446 f = functools.partial(self._find_msb0, bs=delimiter, bytealigned=bytealigned_)
1447 found = f(start=start, end=end)
1448 if not found:
1449 # Initial bits are the whole bitstring being searched
1450 yield self._slice(start, end)
1451 return
1452 # yield the bytes before the first occurrence of the delimiter, even if empty
1453 yield self._slice(start, found[0])
1454 startpos = pos = found[0]
1455 c = 1
1456 while count is None or c < count:
1457 pos += len(delimiter)
1458 found = f(start=pos, end=end)
1459 if not found:
1460 # No more occurrences, so return the rest of the bitstring
1461 yield self._slice(startpos, end)
1462 return
1463 c += 1
1464 yield self._slice(startpos, found[0])
1465 startpos = pos = found[0]
1466 # Have generated count bitstrings, so time to quit.
1467 return
1469 def join(self: TBits, sequence: Iterable[Any]) -> TBits:
1470 """Return concatenation of bitstrings joined by self.
1472 sequence -- A sequence of bitstrings.
1474 """
1475 s = self.__class__()
1476 if len(self) == 0:
1477 # Optimised version that doesn't need to add self between every item
1478 for item in sequence:
1479 s._addright(Bits._create_from_bitstype(item))
1480 return s
1481 else:
1482 sequence_iter = iter(sequence)
1483 try:
1484 s._addright(Bits._create_from_bitstype(next(sequence_iter)))
1485 except StopIteration:
1486 return s
1487 for item in sequence_iter:
1488 s._addright(self)
1489 s._addright(Bits._create_from_bitstype(item))
1490 return s
1492 def tobytes(self) -> bytes:
1493 """Return the bitstring as bytes, padding with zero bits if needed.
1495 Up to seven zero bits will be added at the end to byte align.
1497 """
1498 return self._bitstore.tobytes()
1500 def tobitarray(self) -> bitarray.bitarray:
1501 """Convert the bitstring to a bitarray object."""
1502 if self._bitstore.modified_length is not None:
1503 # Removes the offset and truncates to length
1504 return self._bitstore.getslice(0, len(self))._bitarray
1505 else:
1506 return self._bitstore._bitarray
1508 def tofile(self, f: BinaryIO) -> None:
1509 """Write the bitstring to a file object, padding with zero bits if needed.
1511 Up to seven zero bits will be added at the end to byte align.
1513 """
1514 # If the bitstring is file based then we don't want to read it all in to memory first.
1515 chunk_size = 8 * 100 * 1024 * 1024 # 100 MiB
1516 for chunk in self.cut(chunk_size):
1517 f.write(chunk.tobytes())
1519 def startswith(self, prefix: BitsType, start: Optional[int] = None, end: Optional[int] = None) -> bool:
1520 """Return whether the current bitstring starts with prefix.
1522 prefix -- The bitstring to search for.
1523 start -- The bit position to start from. Defaults to 0.
1524 end -- The bit position to end at. Defaults to len(self).
1526 """
1527 prefix = self._create_from_bitstype(prefix)
1528 start, end = self._validate_slice(start, end)
1529 return self._slice(start, start + len(prefix)) == prefix if end >= start + len(prefix) else False
1531 def endswith(self, suffix: BitsType, start: Optional[int] = None, end: Optional[int] = None) -> bool:
1532 """Return whether the current bitstring ends with suffix.
1534 suffix -- The bitstring to search for.
1535 start -- The bit position to start from. Defaults to 0.
1536 end -- The bit position to end at. Defaults to len(self).
1538 """
1539 suffix = self._create_from_bitstype(suffix)
1540 start, end = self._validate_slice(start, end)
1541 return self._slice(end - len(suffix), end) == suffix if start + len(suffix) <= end else False
1543 def all(self, value: Any, pos: Optional[Iterable[int]] = None) -> bool:
1544 """Return True if one or many bits are all set to bool(value).
1546 value -- If value is True then checks for bits set to 1, otherwise
1547 checks for bits set to 0.
1548 pos -- An iterable of bit positions. Negative numbers are treated in
1549 the same way as slice indices. Defaults to the whole bitstring.
1551 """
1552 value = 1 if bool(value) else 0
1553 if pos is None:
1554 return self._bitstore.all_set() if value else not self._bitstore.any_set()
1555 for p in pos:
1556 if self._bitstore.getindex(p) != value:
1557 return False
1558 return True
1560 def any(self, value: Any, pos: Optional[Iterable[int]] = None) -> bool:
1561 """Return True if any of one or many bits are set to bool(value).
1563 value -- If value is True then checks for bits set to 1, otherwise
1564 checks for bits set to 0.
1565 pos -- An iterable of bit positions. Negative numbers are treated in
1566 the same way as slice indices. Defaults to the whole bitstring.
1568 """
1569 value = 1 if bool(value) else 0
1570 if pos is None:
1571 return self._bitstore.any_set() if value else not self._bitstore.all_set()
1572 for p in pos:
1573 if self._bitstore.getindex(p) == value:
1574 return True
1575 return False
1577 def count(self, value: Any) -> int:
1578 """Return count of total number of either zero or one bits.
1580 value -- If bool(value) is True then bits set to 1 are counted, otherwise bits set
1581 to 0 are counted.
1583 >>> Bits('0xef').count(1)
1584 7
1586 """
1587 # count the number of 1s (from which it's easy to work out the 0s).
1588 count = self._bitstore.count(1)
1589 return count if value else len(self) - count
1591 @staticmethod
1592 def _format_bits(bits: Bits, bits_per_group: int, sep: str, dtype: Dtype,
1593 colour_start: str, colour_end: str, width: Optional[int]=None) -> Tuple[str, int]:
1594 get_fn = dtype.get_fn
1595 if dtype.name == 'bytes': # Special case for bytes to print one character each.
1596 get_fn = Bits._getbytes_printable
1597 if dtype.name == 'bool': # Special case for bool to print '1' or '0' instead of `True` or `False`.
1598 get_fn = dtype_register.get_dtype('uint', bits_per_group).get_fn
1599 if bits_per_group == 0:
1600 x = str(get_fn(bits))
1601 else:
1602 # Left-align for fixed width types when msb0, otherwise right-align.
1603 align = '<' if dtype.name in ['bin', 'oct', 'hex', 'bits', 'bytes'] and not bitstring.options.lsb0 else '>'
1604 chars_per_group = 0
1605 if dtype_register[dtype.name].bitlength2chars_fn is not None:
1606 chars_per_group = dtype_register[dtype.name].bitlength2chars_fn(bits_per_group)
1607 x = sep.join(f"{str(get_fn(b)): {align}{chars_per_group}}" for b in bits.cut(bits_per_group))
1609 chars_used = len(x)
1610 padding_spaces = 0 if width is None else max(width - len(x), 0)
1611 x = colour_start + x + colour_end
1612 # Pad final line with spaces to align it
1613 if bitstring.options.lsb0:
1614 x = ' ' * padding_spaces + x
1615 else:
1616 x += ' ' * padding_spaces
1617 return x, chars_used
1619 @staticmethod
1620 def _chars_per_group(bits_per_group: int, fmt: Optional[str]):
1621 """How many characters are needed to represent a number of bits with a given format."""
1622 if fmt is None or dtype_register[fmt].bitlength2chars_fn is None:
1623 return 0
1624 return dtype_register[fmt].bitlength2chars_fn(bits_per_group)
1626 @staticmethod
1627 def _bits_per_char(fmt: str):
1628 """How many bits are represented by each character of a given format."""
1629 if fmt not in ['bin', 'oct', 'hex', 'bytes']:
1630 raise ValueError
1631 return 24 // dtype_register[fmt].bitlength2chars_fn(24)
1633 def _pp(self, dtype1: Dtype, dtype2: Optional[Dtype], bits_per_group: int, width: int, sep: str, format_sep: str,
1634 show_offset: bool, stream: TextIO, lsb0: bool, offset_factor: int) -> None:
1635 """Internal pretty print method."""
1636 colour = Colour(not bitstring.options.no_color)
1637 name1 = dtype1.name
1638 name2 = dtype2.name if dtype2 is not None else None
1639 if dtype1.variable_length:
1640 raise ValueError(f"Can't use Dtype '{dtype1}' in pp() as it has a variable length.")
1641 if dtype2 is not None and dtype2.variable_length:
1642 raise ValueError(f"Can't use Dtype '{dtype2}' in pp() as it has a variable length.")
1643 offset_width = 0
1644 offset_sep = ' :' if lsb0 else ': '
1645 if show_offset:
1646 # This could be 1 too large in some circumstances. Slightly recurrent logic needed to fix it...
1647 offset_width = len(str(len(self))) + len(offset_sep)
1648 if bits_per_group > 0:
1649 group_chars1 = Bits._chars_per_group(bits_per_group, name1)
1650 group_chars2 = Bits._chars_per_group(bits_per_group, name2)
1651 # The number of characters that get added when we add an extra group (after the first one)
1652 total_group_chars = group_chars1 + group_chars2 + len(sep) + len(sep) * bool(group_chars2)
1653 width_excluding_offset_and_final_group = width - offset_width - group_chars1 - group_chars2 - len(
1654 format_sep) * bool(group_chars2)
1655 width_excluding_offset_and_final_group = max(width_excluding_offset_and_final_group, 0)
1656 groups_per_line = 1 + width_excluding_offset_and_final_group // total_group_chars
1657 max_bits_per_line = groups_per_line * bits_per_group # Number of bits represented on each line
1658 else:
1659 assert bits_per_group == 0 # Don't divide into groups
1660 width_available = width - offset_width - len(format_sep) * (name2 is not None)
1661 width_available = max(width_available, 1)
1662 if name2 is None:
1663 max_bits_per_line = width_available * Bits._bits_per_char(name1)
1664 else:
1665 chars_per_24_bits = dtype_register[name1].bitlength2chars_fn(24) + dtype_register[name2].bitlength2chars_fn(24)
1666 max_bits_per_line = 24 * (width_available // chars_per_24_bits)
1667 if max_bits_per_line == 0:
1668 max_bits_per_line = 24 # We can't fit into the width asked for. Show something small.
1669 assert max_bits_per_line > 0
1671 bitpos = 0
1672 first_fb_width = second_fb_width = None
1673 for bits in self.cut(max_bits_per_line):
1674 offset_str = ''
1675 if show_offset:
1676 offset = bitpos // offset_factor
1677 bitpos += len(bits)
1678 if bitstring.options.lsb0:
1679 offset_str = colour.green + offset_sep + f'{offset: <{offset_width - len(offset_sep)}}' + colour.off
1680 else:
1681 offset_str = colour.green + f'{offset: >{offset_width - len(offset_sep)}}' + offset_sep + colour.off
1683 fb1, chars_used = Bits._format_bits(bits, bits_per_group, sep, dtype1, colour.purple, colour.off, first_fb_width)
1684 if first_fb_width is None:
1685 first_fb_width = chars_used
1687 fb2 = ''
1688 if dtype2 is not None:
1689 fb2, chars_used = Bits._format_bits(bits, bits_per_group, sep, dtype2, colour.blue, colour.off, second_fb_width)
1690 if second_fb_width is None:
1691 second_fb_width = chars_used
1692 fb2 = format_sep + fb2
1694 if bitstring.options.lsb0 is True:
1695 line_fmt = fb1 + fb2 + offset_str + '\n'
1696 else:
1697 line_fmt = offset_str + fb1 + fb2 + '\n'
1698 stream.write(line_fmt)
1699 return
1701 @staticmethod
1702 def _process_pp_tokens(token_list, fmt):
1703 has_length_in_fmt = True
1704 if len(token_list) == 1:
1705 dtype1 = Dtype(*utils.parse_name_length_token(token_list[0]))
1706 dtype2 = None
1707 bits_per_group = dtype1.bitlength
1708 if bits_per_group is None:
1709 has_length_in_fmt = False
1710 bits_per_group = {'bin': 8, 'hex': 8, 'oct': 12, 'bytes': 32}.get(dtype1.name)
1711 if bits_per_group is None:
1712 raise ValueError(f"No length or default length available for pp() format '{fmt}'.")
1713 elif len(token_list) == 2:
1714 dtype1 = Dtype(*utils.parse_name_length_token(token_list[0]))
1715 dtype2 = Dtype(*utils.parse_name_length_token(token_list[1]))
1716 if dtype1.bitlength is not None and dtype2.bitlength is not None and dtype1.bitlength != dtype2.bitlength:
1717 raise ValueError(
1718 f"Differing bit lengths of {dtype1.bitlength} and {dtype2.bitlength} in format string '{fmt}'.")
1719 bits_per_group = dtype1.bitlength if dtype1.bitlength is not None else dtype2.bitlength
1720 if bits_per_group is None:
1721 has_length_in_fmt = False
1722 try:
1723 bits_per_group = 2 * Bits._bits_per_char(dtype1.name) * Bits._bits_per_char(dtype2.name)
1724 except ValueError:
1725 raise ValueError(f"Can't find a default bitlength to use for pp() format '{fmt}'.")
1726 if bits_per_group >= 24:
1727 bits_per_group //= 2
1728 else:
1729 raise ValueError(
1730 f"Only one or two tokens can be used in an pp() format - '{fmt}' has {len(token_list)} tokens.")
1731 return dtype1, dtype2, bits_per_group, has_length_in_fmt
1733 def pp(self, fmt: Optional[str] = None, width: int = 120, sep: str = ' ',
1734 show_offset: bool = True, stream: TextIO = sys.stdout) -> None:
1735 """Pretty print the bitstring's value.
1737 fmt -- Printed data format. One or two of 'bin', 'oct', 'hex' or 'bytes'.
1738 The number of bits represented in each printed group defaults to 8 for hex and bin,
1739 12 for oct and 32 for bytes. This can be overridden with an explicit length, e.g. 'hex:64'.
1740 Use a length of 0 to not split into groups, e.g. `bin:0`.
1741 width -- Max width of printed lines. Defaults to 120. A single group will always be printed
1742 per line even if it exceeds the max width.
1743 sep -- A separator string to insert between groups. Defaults to a single space.
1744 show_offset -- If True (the default) shows the bit offset in the first column of each line.
1745 stream -- A TextIO object with a write() method. Defaults to sys.stdout.
1747 >>> s.pp('hex16')
1748 >>> s.pp('b, h', sep='_', show_offset=False)
1750 """
1751 colour = Colour(not bitstring.options.no_color)
1752 if fmt is None:
1753 fmt = 'bin, hex' if len(self) % 8 == 0 and len(self) >= 8 else 'bin'
1754 token_list = utils.preprocess_tokens(fmt)
1755 dtype1, dtype2, bits_per_group, has_length_in_fmt = Bits._process_pp_tokens(token_list, fmt)
1756 trailing_bit_length = len(self) % bits_per_group if has_length_in_fmt and bits_per_group else 0
1757 data = self if trailing_bit_length == 0 else self[0: -trailing_bit_length]
1758 format_sep = " : " # String to insert on each line between multiple formats
1759 tidy_fmt = colour.purple + str(dtype1) + colour.off
1760 if dtype2 is not None:
1761 tidy_fmt += ', ' + colour.blue + str(dtype2) + colour.off
1762 output_stream = io.StringIO()
1763 len_str = colour.green + str(len(self)) + colour.off
1764 output_stream.write(f"<{self.__class__.__name__}, fmt='{tidy_fmt}', length={len_str} bits> [\n")
1765 data._pp(dtype1, dtype2, bits_per_group, width, sep, format_sep, show_offset,
1766 output_stream, bitstring.options.lsb0, 1)
1767 output_stream.write("]")
1768 if trailing_bit_length != 0:
1769 output_stream.write(" + trailing_bits = " + str(self[-trailing_bit_length:]))
1770 output_stream.write("\n")
1771 stream.write(output_stream.getvalue())
1772 return
1774 def copy(self: TBits) -> TBits:
1775 """Return a copy of the bitstring."""
1776 # Note that if you want a new copy (different ID), use _copy instead.
1777 # The copy can return self as it's immutable.
1778 return self
1780 @classmethod
1781 def fromstring(cls: TBits, s: str, /) -> TBits:
1782 """Create a new bitstring from a formatted string."""
1783 x = super().__new__(cls)
1784 x._bitstore = bitstore_helpers.str_to_bitstore(s)
1785 return x
1787 len = length = property(_getlength, doc="The length of the bitstring in bits. Read only.")