Source code for pcapkit.corekit.fields.byteorder

# -*- coding: utf-8 -*-
"""byte-order field helpers

:mod:`pcapkit.corekit.fields.byteorder` holds the field callback that reads a
capture file's byte order out of the packet data. The record header of a
classic PCAP file (:mod:`~pcapkit.protocols.schema.misc.pcap.frame`) and the
blocks of a PCAP-NG file (:mod:`~pcapkit.protocols.schema.misc.pcapng`) both use
it. It acts on a :class:`~pcapkit.corekit.fields.numbers.NumberField` and on the
``__packet__`` key :class:`~pcapkit.corekit.fields.misc.SchemaField` hands a
nested schema, so it lives with the fields rather than with either schema
(:issue:`1711`).

.. versionadded:: 1.5.0

   :func:`byteorder_callback` moves here from
   :mod:`pcapkit.protocols.schema.misc.pcap.frame` (:issue:`1711`).

"""

import sys
from typing import TYPE_CHECKING

__all__ = ['packet_byteorder', 'byteorder_callback']

if TYPE_CHECKING:
    from typing import Any

    from typing_extensions import Literal

    from pcapkit.corekit.fields.numbers import NumberField


[docs] def packet_byteorder(packet: 'dict[str, Any]') -> 'Literal["big", "little"]': """Byte order declared for the file or section that ``packet`` belongs to. A nested schema is handed its parent's packet data under a ``__packet__`` key (see :meth:`SchemaField.pack <pcapkit.corekit.fields.misc.SchemaField.pack>`), so the byte order may live one level up. Args: packet: Packet data. Returns: Byte order of the enclosing file or section, falling back to the host byte order when the packet data declares none. """ if 'byteorder' not in packet and '__packet__' in packet: return packet['__packet__'].get('byteorder', sys.byteorder) return packet.get('byteorder', sys.byteorder)
[docs] def byteorder_callback(field: 'NumberField', packet: 'dict[str, Any]') -> 'None': """Update byte order of a PCAP or PCAP-NG file. Args: field: Field instance. packet: Packet data. Notes: ``byteorder`` is the key a caller has to seed, and :func:`packet_byteorder` is what reads it. :meth:`Frame.pack <pcapkit.protocols.misc.pcap.frame.Frame.pack>` and :meth:`Frame.unpack <pcapkit.protocols.misc.pcap.frame.Frame.unpack>` both write it from the global header's magic number. A PCAP-NG Section Header Block writes it from its own Byte-Order Magic (see :func:`~pcapkit.protocols.schema.misc.pcapng.shb_byteorder_callback`), and the blocks, options and records of that section read it, nested or not. The fallback to :data:`sys.byteorder` is for a schema packed or unpacked on its own, with no header to ask. That also means a *misspelled* key looks exactly like an absent one and reports nothing: every field would be read in the host's order rather than the file's, which is right by coincidence on a little-endian capture and byte-swapped on a big-endian one. See :file:`tests/protocols/misc/pcap/test_frame_endian_runtime.py` for the fixtures that take the other side of the branch. """ field._byteorder = packet_byteorder(packet)