Core API: Integers and Floats

construct.FormatField(endianity, format)

Field that uses struct module to pack and unpack CPU-sized integers and floats and booleans. This is used to implement most Int* Float* fields, but for example cannot pack 24-bit integers, which is left to BytesInteger class. For booleans I also recommend using Flag class instead.

See struct module documentation for instructions on crafting format strings.

Parses into an integer or float or boolean. Builds from an integer or float or boolean into specified byte count and endianness. Size is determined by struct module according to specified format string.

Parameters:
  • endianity – string, character like: < > =

  • format – string, character like: B H L Q b h l q e f d ?

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • FormatFieldError – wrong format string, or struct.(un)pack complained about the value

Example:

>>> d = FormatField(">", "H") or Int16ub
>>> d.parse(b"\x01\x00")
256
>>> d.build(256)
b"\x01\x00"
>>> d.sizeof()
2
construct.BytesInteger(length, signed=False, swapped=False)

Field that packs integers of arbitrary size. Int24* fields use this class.

Parses into an integer. Builds from an integer into specified byte count and endianness. Size is specified in ctor.

Analog to BitsInteger which operates on bits. In fact:

BytesInteger(n) <--> Bitwise(BitsInteger(8*n))
BitsInteger(8*n) <--> Bytewise(BytesInteger(n))

Byte ordering refers to bytes (chunks of 8 bits) so, for example:

BytesInteger(n, swapped=True) <--> Bitwise(BitsInteger(8*n, swapped=True))
Parameters:
  • length – integer or context lambda, number of bytes in the field

  • signed – bool, whether the value is signed (two’s complement), default is False (unsigned)

  • swapped – bool or context lambda, whether to swap byte order (little endian), default is False (big endian)

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • IntegerError – length is negative or zero

  • IntegerError – value is not an integer

  • IntegerError – number does not fit given width and signed parameters

Can propagate any exception from the lambda, possibly non-ConstructError.

Example:

>>> d = BytesInteger(4) or Int32ub
>>> d.parse(b"abcd")
1633837924
>>> d.build(1)
b'\x00\x00\x00\x01'
>>> d.sizeof()
4
construct.BitsInteger(length, signed=False, swapped=False)

Field that packs arbitrarily large (or small) integers. Some fields (Bit Nibble Octet) use this class. Must be enclosed in Bitwise context.

Parses into an integer. Builds from an integer into specified bit count and endianness. Size (in bits) is specified in ctor.

Analog to BytesInteger which operates on bytes. In fact:

BytesInteger(n) <--> Bitwise(BitsInteger(8*n))
BitsInteger(8*n) <--> Bytewise(BytesInteger(n))

Note that little-endianness is only defined for multiples of 8 bits.

Byte ordering (i.e. swapped parameter) refers to bytes (chunks of 8 bits) so, for example:

BytesInteger(n, swapped=True) <--> Bitwise(BitsInteger(8*n, swapped=True))

Swapped argument was recently fixed. To obtain previous (faulty) behavior, you can use ByteSwapped, BitsSwapped and Bitwise in whatever particular order (see examples).

Parameters:
  • length – integer or context lambda, number of bits in the field

  • signed – bool, whether the value is signed (two’s complement), default is False (unsigned)

  • swapped – bool or context lambda, whether to swap byte order (little endian), default is False (big endian)

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • IntegerError – length is negative or zero

  • IntegerError – value is not an integer

  • IntegerError – number does not fit given width and signed parameters

  • IntegerError – little-endianness selected but length is not multiple of 8 bits

Can propagate any exception from the lambda, possibly non-ConstructError.

Examples:

>>> d = Bitwise(BitsInteger(8)) or Bitwise(Octet)
>>> d.parse(b"\x10")
16
>>> d.build(255)
b'\xff'
>>> d.sizeof()
1

Obtaining other byte or bit orderings:

>>> d = BitsInteger(2)
>>> d.parse(b'\x01\x00') # Bit-Level Big-Endian
2
>>> d = ByteSwapped(BitsInteger(2))
>>> d.parse(b'\x01\x00') # Bit-Level Little-Endian
1
>>> d = BitsInteger(16) # Byte-Level Big-Endian, Bit-Level Big-Endian
>>> d.build(5 + 19*256)
b'\x00\x00\x00\x01\x00\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x01'
>>> d = BitsInteger(16, swapped=True) # Byte-Level Little-Endian, Bit-Level Big-Endian
>>> d.build(5 + 19*256)
b'\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x00\x01\x01'
>>> d = ByteSwapped(BitsInteger(16)) # Byte-Level Little-Endian, Bit-Level Little-Endian
>>> d.build(5 + 19*256)
b'\x01\x00\x01\x00\x00\x00\x00\x00\x01\x01\x00\x00\x01\x00\x00\x00'
>>> d = ByteSwapped(BitsInteger(16, swapped=True)) # Byte-Level Big-Endian, Bit-Level Little-Endian
>>> d.build(5 + 19*256)
b'\x01\x01\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00'
construct.VarInt()

VarInt encoded unsigned integer. Each 7 bits of the number are encoded in one byte of the stream, where leftmost bit (MSB) is unset when byte is terminal. Scheme is defined at Google site related to Protocol Buffers.

Can only encode non-negative numbers.

Parses into an integer. Builds from an integer. Size is undefined.

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • IntegerError – given a negative value, or not an integer

Example:

>>> VarInt.build(1)
b'\x01'
>>> VarInt.build(2**100)
b'\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x04'
construct.ZigZag()

ZigZag encoded signed integer. This is a variant of VarInt encoding that also can encode negative numbers. Scheme is defined at Google site related to Protocol Buffers.

Can also encode negative numbers.

Parses into an integer. Builds from an integer. Size is undefined.

Raises:
  • StreamError – requested reading negative amount, could not read enough bytes, requested writing different amount than actual data, or could not write all bytes

  • IntegerError – given not an integer

Example:

>>> ZigZag.build(-3)
b'\x05'
>>> ZigZag.build(3)
b'\x06'