Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

struct

import struct

This module provides functions for converting between Zuri values and C/C++/Rust structs and vice-versa in the binary format.

The pack and unpack functions behave similarly as the pack and unpack functions from Perl and PHP (more similar to the PHP version) with few major extensions to their format language.

Format language

A format string is a sequence of /-separated segments. Each segment is one or more CODE[COUNT] groups, optionally followed by :NAME to label the field(s) that group produces when unpacking:

  "Nsize:len/A16:name/C4"
  • CODE is one of the format characters in the table below. - COUNT is a decimal integer, or * to mean “the rest” (the whole remaining argument for a string-like code, or every remaining argument/byte for a numeric code). Omitted means 1.
  • :NAME names the field(s) produced by that ONE group when unpacking. A count > 1 numbers the keys NAME1, NAME2, … A segment carrying a :NAME may only contain a single group. - A group with no :NAME gets a purely numeric key that runs once, globally, for the whole format string; it never resets and so never silently overwrites an earlier unnamed field.

Format codes

Code | Bytes | Meaning —–|—––|–––– a | count | NUL-padded string A | count | SPACE-padded string (trailing NUL/space trimmed on unpack) Z | count | NUL-padded, NUL-terminated string (C-string semantics) h | ceil(count/2) | Hex string, low nibble first H | ceil(count/2) | Hex string, high nibble first c | 1 | signed 8-bit integer C | 1 | unsigned 8-bit integer ? | 1 | boolean s | 2 | signed 16-bit integer, native byte order S | 2 | unsigned 16-bit integer, native byte order n | 2 | unsigned 16-bit integer, big-endian v | 2 | unsigned 16-bit integer, little-endian i | 4 | signed 32-bit integer, native byte order I | 4 | unsigned 32-bit integer, native byte order l | 4 | signed 32-bit integer, native byte order L | 4 | unsigned 32-bit integer, native byte order N | 4 | unsigned 32-bit integer, big-endian V | 4 | unsigned 32-bit integer, little-endian q | 8 | signed 64-bit integer, native byte order Q | 8 | unsigned 64-bit integer, native byte order J | 8 | unsigned 64-bit integer, big-endian P | 8 | unsigned 64-bit integer, little-endian u | 16 | signed 128-bit integer, little-endian U | 16 | unsigned 128-bit integer, little-endian f | 4 | float, native byte order g | 4 | float, little-endian G | 4 | float, big-endian d | 8 | double, native byte order e | 8 | double, little-endian E | 8 | double, big-endian w | 2 | IEEE-754 half-precision float, little-endian W | 2 | IEEE-754 half-precision float, big-endian x | count | NUL byte(s); consumes no argument X | count | back up count byte(s) Z |; | (see above) @ |; | seek/pad to absolute position count

Integer precision

Zuri numbers are IEEE-754 doubles, which can only represent integers exactly up to 2^53. Every integer-producing code here (q/Q/J/P, and the new u/U) automatically promotes its result to a bigint Value instead of a number whenever the unpacked value falls outside that safe range, rather than silently losing precision. Packing accepts either a number or a bigint for every integer code.

The struct API

Every public name in struct, wherever it is declared. Each links to the page that documents it.

NameKindSummary
struct.calcsizefunctionCalculates the size of the buffer needed to pack the given values according to the specified format.
struct.iter_unpackfunctionUnpacks a buffer as a repeated sequence of fixed-size records until exhausted, returning a list of…
struct.packfunctionPacks the given arguments into a bytes object according to the specified format.
struct.pack_fromfunctionSame as pack() except that instead of accepting arbitrary values after format, it expects the values to be…
struct.pack_intofunctionPacks directly into an existing bytes object at offset, growing it (zero-padded) if it isn’t long enough…
struct.unpackfunctionUnpacks from bytes or a string into a dictionary based on the given format.
struct.unpack_fromfunctionThe pack_from() equivalent of unpack().

Functions

pack()

struct.pack(format: string, ...values: list) -> bytes

Packs the given arguments into a bytes object according to the specified format.

Parameters

  • format (string)
  • any... — args

Returns bytes

unpack()

struct.unpack(format: string, data: bytes|string, offset: ?number) -> any

Unpacks from bytes or a string into a dictionary based on the given format.

  • You may have to name the different format codes and separate them by a slash / to return a string indexed dictionary for easy reference of the destructed parts. If a repeater argument is present, then each of the dictionary keys will have a sequence number behind the given name.

  • offset is the index of the bytes/string to begin unpacking from

Important If you do not name an element, numeric indices starting from 1 are used. Be aware that if you have more than one unnamed element, some data is overwritten because the numbering restarts from 1 for each element.

Parameters

  • format (string)
  • data (bytes|string)
  • offset (?number) — Default value is 0

Returns any

pack_from()

struct.pack_from(format: string, args: list) -> bytes

Same as pack() except that instead of accepting arbitrary values after format, it expects the values to be in a list.

Parameters

  • format (string)
  • args (list)

Returns bytes

unpack_from()

struct.unpack_from(format: string, data: bytes|string, offset: ?number) -> any

The pack_from() equivalent of unpack(). This function is essentially the same as unpack() and was kept for symmetry with pack_from().

Parameters

  • format (string)
  • data (bytes|string)
  • offset (?number) — Default value is 0

Returns any

See also: unpack()

pack_into()

struct.pack_into(format: string, buffer: bytes, offset: number, ...values: list) -> number

Packs directly into an existing bytes object at offset, growing it (zero-padded) if it isn’t long enough and returns the number of elements written.

This function avoids an allocate-then-copy round trip when assembling a larger buffer field by field.

Parameters

  • format (string)
  • buffer (bytes)
  • offset (number)
  • any... — values

Returns number

calcsize()

struct.calcsize(format: string) -> number

Calculates the size of the buffer needed to pack the given values according to the specified format. It raises an error if the format is invalid or if the values cannot be packed according to the format or if it contains a * repeat anywhere, since that has no size independent of actual data.

Parameters

  • format (string)

Returns number

Raises Error

iter_unpack()

struct.iter_unpack(format: string, data: bytes|string) -> list

Unpacks a buffer as a repeated sequence of fixed-size records until exhausted, returning a list of dictionaries. The format string must not contain any * repeaters, since that would make the record size variable.

Parameters

  • format (string)
  • data (bytes|string)

Returns list


2022, Richard Ore and The Zuri Contributors