Numerical Fields

Sized Fields

class pcapkit.corekit.fields.numbers.Int32Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Integer value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as False, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.UInt32Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Unsigned integer value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as True, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.Int16Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Short integer value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as False, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.UInt16Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Unsigned short integer value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as True, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.Int64Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Long integer value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as False, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.UInt64Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Unsigned long integer value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as True, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.Int8Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Byte value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as False, contradicting the sign this class fixes.

class pcapkit.corekit.fields.numbers.UInt8Field(length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: NumberField

Unsigned byte value for protocol fields.

Parameters:
Raises:

FieldValueError – If signed is given as True, contradicting the sign this class fixes.

Enumeration Fields

class pcapkit.corekit.fields.numbers.EnumField(length, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, namespace=None, callback=lambda *_: ...)[source]

Bases: NumberField[IntEnum | aenum.IntEnum]

Enumerated value for protocol fields.

Parameters:
  • length (int | Callable[[dict[str, Any]], int]) – Field size (in bytes); if a callable is given, it should return an integer value and accept the current packet as its only argument.

  • default (IntEnum | aenum.IntEnum | NoValueType) – Field default value, if any.

  • signed (bool | None) – Whether the field is signed; None defers to the class-level __signed__, which this class leaves unset and so means unsigned.

  • byteorder (Literal['little', 'big']) – Field byte order.

  • bit_length (int | None) – Field bit length.

  • namespace (Type[IntEnum] | Type[aenum.IntEnum] | None) – Field namespace (a enum.IntEnum class).

  • callback (Callable[[Self, dict[str, Any]], None]) – Callback function to be called upon self.__call__.

Notes

A wire value the namespace registry has no member for resolves to a nameless pseudo-member rather than failing the parse – see post_process().

post_process(value, packet)[source]

Process field value after parsing (unpacked).

Parameters:
Return type:

IntEnum | aenum.IntEnum

Returns:

Processed field value – the registry member declared for the value, or a nameless pseudo-member carrying the value itself when the registry declares none.

Raises:

BaseError – Whatever in-library error the registry raised for the value, re-raised untouched.

Notes

The registry is consulted through its constructor, which raises for a value no member and no _missing_ rule accounts for. That raise is aenum’s own bare ValueError: not one of pcapkit.utilities.exceptions, so a caller cannot tell it from a bug of its own, and not an EOFError, so Extractor.record_frames does not catch it. Left to propagate, one unassigned code would cost the whole extraction.

It would also make the “unknown” reader the formats require unreachable for any genuinely unassigned code – PCAP-NG’s UnknownBlock, and the unassigned option readers of IPv4, TCP, HOPOPT, MH and HIP – because the lookup would fail before the dispatch that selects it. PCAP-NG repeats a block’s total length at both ends precisely so that a reader can skip a block type it does not recognise; that skip is what this fallback keeps working. See GitHub issue #701.

The fallback is the same nameless pseudo-member this method already builds for a field carrying no registry at all, so it is a value shape the package already produces and the dump layer already renders – as <unknown>::<unassigned> [28], through render_enum(), not through its name is None branch (#648), which a member named <unassigned> never takes – and one an int-keyed dispatch registry looks up by value like any declared member. It is built per value rather than grafted onto the registry with aenum.extend_enum, for two reasons: a capture carrying many distinct unassigned codes would otherwise grow a process-global registry without bound, which is the growth Protocol._lookup_registry exists to avoid; and a stdlib enum.IntEnum registry is then handled exactly like an aenum.IntEnum one.

Only a foreign rejection is absorbed. A registry rejecting a value with one of pcapkit.utilities.exceptions has made a deliberate decision that this layer – which sees only that the value arrived in a field of some width – is in no position to overrule, so an in-library error propagates unchanged and it is only aenum’s and enum’s “no member has this value” that becomes a pseudo-member. That is what keeps the fallback from being an unconditional except ValueError: pass.

No registry under pcapkit.const raises an in-library error from its guard, and deliberately so: a generated guard raises a bare, unlogged ValueError precisely because the except ValueError fallback of get() has to keep catching it (GitHub issues #584 and #647). That bare ValueError is also how a generated guard bounds its registry to a width, rejecting a value outside 0 <= value <= N. Bit-flag registries such as pcapkit.const.tcp.flags.Flags do so, and so do plain ones such as pcapkit.const.ipv4.option_number.OptionNumber, which is the namespace of a plain EnumField. That is harmless: the out-of-width rejection is the bare ValueError this method falls back on, so no in-library guard loses its force through this method. The distinction is therefore for a registry registered from outside pcapkit.const, which has no such obligation to stay quiet.

Octets carrying bits outside bit_length that NumberField.post_process() recorded resolve to a member that records them too, so that packing it writes them back. A registry member is shared, so that one is an unregistered copy of it, built by _unregistered_member(): isinstance against the registry and equality with the member still hold, identity does not. See GitHub issue #1488.

Changed in version 1.5.0: A value the registry has no member for resolves to a nameless pseudo-member, where aenum’s bare ValueError escaped (#701).

_pseudo_member(value)[source]

Build the bounded nameless pseudo-member this method falls back to when value is a foreign miss rather than an in-library rejection.

Return type:

IntEnum | aenum.IntEnum

Returns:

A single-member, throwaway enum.IntEnum instance, built fresh per call rather than aenum.extend_enum-ed onto self._namespace, per this method’s own docstring above.

static _unregistered_member(namespace, value, name='<unassigned>', **attrs)[source]

Build a member of namespace, absent from every one of its own lookup tables, for a value a parse – rather than a direct call to the registry’s own get() – resolved without anyone asking for a name.

GitHub issue #575: the owner’s ruling is that an unassigned wire value should resolve to a real member of the registry the field names – isinstance against it and every ancestor holds, and it renders and dispatches exactly like a declared one – provided building it never grows the registry. This is what gets there: it calls namespace’s own storage base’s __new__ directly – str or int, whichever namespace derives from – which skips namespace’s own __new__ entirely, and with it the cls.__registry__.add(...) / cls.__members_ns__[...] = ... line every registry in this package uses to record a member it mints. No entry is added to _member_map_ or _value2member_map_ either, since those are only ever touched by the metaclass machinery aenum.extend_enum drives, which this bypasses completely.

Note

Building a member this way, rather than as some other type altogether, is why PortEnumField.post_process() and OptionEnumField.post_process need this rather than _pseudo_member(): the result answers isinstance(result, AppType) truthfully, which PortEnumField.pre_process() tests before reading .port off it, and Transport._make_port in pcapkit.protocols.transport.transport before passing it through unchanged (see test_a_member_is_still_an_apptype in tests/const/test_const_apptype_split_unit.py); a value that fails them would be a defect of its own.

The member this returns is absent from _value2member_map_, so a value-keyed lookup on it – self._namespace(value) – still raises. Nothing on the parse or reconstruction path does that to a value it just resolved this way, which is what keeps this safe to return from post_process. A direct call to AppType.get() for the same port does not come through here, and it does not mint either: it builds an unregistered member of its own, through the registry’s _unregistered_member – measured on this tree, AppType.get(54321, proto=tcp) returns <TCP.unknown: 54321 [tcp]>, TCP.__members__ does not grow, and a second call with the same port returns an equal member rather than the same one. Two unregistered members for the same value also compare equal without being identical, since AppType and OptionType both define __eq__/__hash__ off an attribute (.port / .opt_value) rather than object identity – harmless for every reader in this package, since none compares one with is or keys a mapping on it expecting identity, but worth knowing before reusing this elsewhere.

pickle and copy.copy()/copy.deepcopy() all reduce an Enum member through Enum.__reduce_ex__, which returns (cls, (value,)) – the one lookup this member is deliberately absent from. A minted member is registered and so round-trips; left alone, this one would not: without the override, an unknown TCP port’s member made pickle.loads(pickle.dumps(member)) raise ValueError: 'unknown [53406 - tcp]' is not a valid TCP – while pickle.dumps still succeeded, so the failure surfaced only on read-back rather than where it was caused.

So __reduce_ex__ is set on the member itself, reducing it to _rebuild_unregistered_member() instead of to a value lookup. Both pickle and copy fetch that attribute with getattr() on the object rather than on its type, so a per-instance override is honoured: verified against the C pickle accelerator on every protocol from 0 to 5, against the pure-Python pickle._Pickler, and against copy.copy()/copy.deepcopy() both as they are on 3.11+ and with CPython’s Enum.__copy__/__deepcopy__ deleted to emulate 3.10, where those two do not exist. Rebuilding re-enters this method rather than namespace.__new__, so an unpickled member is unregistered exactly as the original was and the registry does not grow – TCP.__members__ measured unchanged before and after. On 3.11+ copy/deepcopy still return the member itself, since Enum.__copy__ short-circuits ahead of any reduction; on 3.10 they return an equal rebuilt one, which is the same answer for an immutable value.

Parameters:
  • namespace (Type[IntEnum] | Type[aenum.IntEnum]) – The concrete registry class to build the member as an instance of. isinstance holds against it and every ancestor; it never gains an entry in any of its own tables.

  • value (Any) – The value namespace’s own constructor would have wrapped – e.g. the crafted string __new__() builds from a name, a port and a transport, or __new__()’s equivalent – kept the same shape here so a rendered or re-keyed member reads the same either way.

  • name (str) – The member’s own .name; '<unassigned>' matches every other nameless value this package produces.

  • **attrs (Any) – Extra attributes to set on the returned member, matching the shape the caller’s registry gives its real members – AppType’s .port, .svc and .proto, or OptionType’s .opt_name and .opt_value.

Return type:

Any

Returns:

The unregistered member.

Raises:

TypeError – If namespace derives from neither str nor int – every registry this package builds does one or the other, and guessing wrong for some future one would ship a member silently missing whatever its storage base provides, rather than saying plainly that this needs extending first.

class pcapkit.corekit.fields.numbers.PortEnumField(length, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, namespace=None, callback=lambda *_: ..., *, proto)[source]

Bases: EnumField

Enumerated value for transport-layer port fields.

Parameters:
  • length (int | Callable[[dict[str, Any]], int]) – Field size (in bytes); if a callable is given, it should return an integer value and accept the current packet as its only argument.

  • default (IntEnum | aenum.IntEnum | NoValueType) – Field default value, if any.

  • signed (bool | None) – Whether the field is signed; None defers to the class-level __signed__, which this class leaves unset and so means unsigned.

  • byteorder (Literal['little', 'big']) – Field byte order.

  • bit_length (int | None) – Field bit length.

  • namespace (Type[AppType] | None) – The port registry, i.e. AppType.

  • callback (Callable[[Self, dict[str, Any]], None]) – Callback function to be called upon self.__call__.

  • proto (TransportProtocol) – The transport protocol whose ports this field carries – a single TransportProtocol member, which is what tells e.g. TCP/80 from UDP/80. The TCP, UDP and SCTP schemas each pass their own.

Important

This class is specifically designed for AppType as it is actually an aenum.StrEnum class.

Added in version 1.5.0.

pre_process(value, packet)[source]

Process field value before construction (packing).

Parameters:
Return type:

int | bytes

Returns:

Processed field value.

Raises:

FieldValueError – If value is a port outside this field’s width, i.e. 0-65535 for the two-octet TCP, UDP and SCTP ports.

Notes

NumberField.pre_process() masks a value to the field’s width rather than range-checking it, so without this check a schema built directly would write port 70000 as 0x1170 and -1 as 0xffff. A port is a whole field with no bits to carry outside its width, so the check costs no wire value its round trip: every port post_process() can return is in range. The bound is the one post_process() tests. See GitHub issue #2314.

post_process(value, packet)[source]

Process field value after parsing (unpacked).

Parameters:
Return type:

AppType

Returns:

Processed field value – the registry member declared for the port, or an unregistered member of the same registry, carrying the port itself, when the registry declares none.

Notes

This peeks at what AppType.get() itself would consult – the per-port rows via __registry__.getlist, then the documented IANA spans via _missing_() – and only calls get once one of those is known to hold. It is not a guard against growth: get answers a port neither accounts for with an unregistered member rather than minting one (GitHub issue #860), and the registry does not grow either way (#1774). It exists because that member is not the one a parse needs. get builds it through AppType._unregistered_member, which installs no __reduce_ex__, so pickle.loads(pickle.dumps(...)) raises ValueError: 'unknown [50000 - tcp]' is not a valid TCP; and its .name is 'unknown', so it dumps as TCP::unknown [...] rather than as the TCP::<unassigned> [...] of every other unassigned wire value. A genuine miss therefore builds its member through EnumField._unregistered_member() instead.

That member carries the registry’s own __transport__, as get’s does, rather than self._proto. The two are the same member for each of the TCP, UDP and SCTP schemas, but a composite built by hand such as TransportProtocol.tcp | TransportProtocol.udp is a bare int (3, which dispatches to SCTP), and reading .name off it would raise AttributeError on a miss get resolves.

A port outside this field’s own width is rejected before any of that, rather than being let through to _missing_(), which raises a bare ValueError for it. That call sits inside an except ValueError that absorbs a foreign miss, and AppType.get() rejects the out-of-range case deliberately, so that it is never minted over – a catch keyed on exception type alone cannot see the difference between that and a “no member has this value”, so it would quietly turn the rejection into a miss. Within the width, _missing_ raises for no port of any per-transport registry: it returns a member for a documented span and None otherwise. Checking the width first needs no exception-based distinction at all. self.length is the field’s own declared byte width (2 for every caller of this class, hence 0-65535) rather than a hard-coded 65535 borrowed from _missing_()’s own guard, so the two stay in lockstep by construction.

Bitmap Fields

class pcapkit.corekit.fields.numbers.BitmapField(length, namespace, *, remainder=None, flags=None, byteorder='big', callback=lambda *_: ...)[source]

Bases: NumberField

Integer word for protocol fields, split into subfields numbered from its least-significant bit.

The word is read as an integer in its byte order first, so a subfield may cross an octet boundary of a little-endian word, which BitField, numbering the bits of the raw octets from the most-significant one, cannot express.

Parameters:
  • length (int) – Field size (in bytes).

  • namespace (dict[str, tuple[int, int]]) – Field namespace (a dict mapping each subfield’s name to a tuple of its start bit, counted from the least-significant bit, and its width in bits).

  • remainder (str | None) – Name the bits no subfield names are kept under, in place; with None, they are kept under __unnamed__ where any is set, as BitField keeps them.

  • flags (Type[Flag] | Type[aenum.Flag] | None) – Flag enumeration remainder holds a member of; with None, it holds an int.

  • byteorder (Literal['little', 'big']) – Field byte order.

  • callback (Callable[[Self, dict[str, Any]], None]) – Callback function to be called upon self.__call__.

Raises:

FieldValueError – If a subfield reaches past the word, two subfields share a bit, or flags is given without remainder.

Added in version 1.6.0.

UNNAMED = '__unnamed__'

Key of the unpacked value that carries the unnamed bits, as BitField.UNNAMED.

property subfields: dict[str, tuple[int, int]]

Each subfield’s start bit and width.

property remainder: str | None

Name the bits no subfield names are kept under.

property remainder_mask: int

Mask of the bits no subfield names.

property flags: type | None

Flag enumeration remainder holds a member of.

pre_process(value, packet)[source]

Process field value before construction (packing).

Parameters:
Return type:

int | bytes

Returns:

Processed field value.

Raises:

FieldValueError – If a subfield is missing or its value does not fit its bits, or the remainder is not an int or sets a subfield’s bit.

post_process(value, packet)[source]

Process field value after parsing (unpacked).

Parameters:
Returns:

a member of the field’s flags where it has them, else an int.

Return type:

dict[str, Any]

Internal Definitions

class pcapkit.corekit.fields.numbers.NumberField[_T: int](length=None, default=NO_VALUE, signed=None, byteorder='big', bit_length=None, callback=lambda *_: ...)[source]

Bases: Field[int], Generic[_T]

Numerical value for protocol fields.

Parameters:
  • length (int | Callable[[dict[str, Any]], int] | None) – Field size (in bytes); if a callable is given, it should return an integer value and accept the current packet as its only argument.

  • default (int | NoValueType) – Field default value, if any.

  • signed (bool | None) – Whether the field is signed; None defers to the class-level __signed__, which this class leaves unset and so means unsigned.

  • byteorder (Literal['little', 'big']) – Field byte order.

  • bit_length (int | None) – Field bit length.

  • callback (Callable[[Self, dict[str, Any]], None]) – Callback function to be called upon self.__call__.

Raises:
  • IntError – If no length is given and __length__ fixes none either.

  • FieldValueError – If signed contradicts a sign already fixed by __signed__ – never from this class, which fixes none.

  • ProtocolError – If bit_length is given negative. Left alone, (1 << bit_length) - 1 raises a bare, uncatchable ValueError (negative shift count) here, before __call__()’s own negative-length guard (#828) or length’s (#805) ever see anything – this one fires at construction time, on the argument itself rather than on a resolved wire length. See GitHub issue #831.

Notes

A subclass such as UInt32Field fixes the sign through __signed__, so signed there is at best redundant. A contradicting value is rejected rather than discarded, since discarding it would make UInt32Field(signed=True) hand back an unsigned field whose values only look wrong once the high bit is set – see GitHub issue #545. Omitting it, or passing the sign the class already fixes, stays legal.

Packing does not range-check a value: pre_process() masks it to bit_length bits, so e.g. 70000 in a two-octet field packs as 0x1170 and -1 as 0xffff, with no error or warning. This is the documented contract a parsed value’s round trip relies on (#1488). A range check belongs in the protocol’s make or in a field whose values have a range of their own, such as PortEnumField (#2314).

property bit_length: int

Field bit length.

__call__(packet)[source]

Update field attributes.

Parameters:

packet (dict[str, Any]) – Packet data.

Return type:

Self

Returns:

New instance of NumberField.

This method will return a new instance of NumberField instead of updating the current instance.

Raises:

ProtocolError – If the resolved length is negative – e.g. a length callback such as lambda pkt: pkt['len'] - 4 resolving below zero once the wire value it reads is smaller than the subtrahend. Left alone, 1 << (length * 8) raises a bare, uncatchable ValueError (negative shift     count) when bit_length was not supplied, before length (see its own ProtocolError guard, #805/#825) or build_template() ever sees the value: this method sets self._bit_length from the resolved length eagerly, as a cache, and shifts by it immediately, so the crash happens on this line rather than on the later, already-guarded ones. See GitHub issue #828. This guard runs regardless of whether bit_length was supplied, so a field constructed with a fixed bit_length and a callable length that resolves negative raises the identical message as one with no bit_length at all, rather than falling through to a template='...-1s' ProtocolError from length later – see GitHub issue #831. A resolved length of exactly 0 is a legitimate empty field (e.g. len=4 above resolving to 0) and is left alone.

Notes

Rebuilding the template here is what applies a callable length, and build_template() recomputes self._need_process as it goes, so the flag and the template always describe the same width. See GitHub issue #591.

build_template(length, signed)[source]

Build template for field.

Parameters:
  • length (int) – Field size (in bytes)

  • signed (bool) – Whether the field is signed

Return type:

str

Returns:

Template for field.

Notes

self._need_process is assigned here rather than only ever raised, so that it always describes the length this template was built for. Only ever setting it True in the fall-through branch would make it a latch: a callable length is a placeholder of -1 at construction, -1 takes the fall-through branch, and the flag would then survive the rebuild in __call__() that resolves the real width. pre_process() would consequently hand bytes to a template that had become >Q – or >I, >H, >B – and struct.pack() would refuse it. See GitHub issue #591.

Assigning it is what tells a placeholder apart from a width that genuinely needs byte packing, without having to remember that a placeholder was ever in play: the answer for -1 is True, the answer for 8 is False, and whichever width is in force now is the one that decides. A callable resolving to, say, 3 still takes the fall-through branch and still gets True, because for 3 that is the correct answer rather than a leftover one.

pre_process(value, packet)[source]

Process field value before construction (packing).

Parameters:
  • value (int) – Field value.

  • packet (dict[str, Any]) – Packet data.

Return type:

int | bytes

Returns:

Processed field value.

Notes

Masking against self._bit_mask truncates the value to the field’s bit length, but it also turns a negative value into its unsigned two’s-complement pattern, which neither struct.pack() nor int.to_bytes() accepts for a signed field. A signed field therefore maps the pattern back into its signed range afterwards, so that e.g. a PCAP-NG section length of -1 (section length not specified) can be written out.

A field packed without having been resolved – so with _length still negative – has its width derived from the value instead, and that rebuild can land on a width struct has a native integer code for. The flag is therefore consulted after the rebuild rather than before it, since deciding first and rebuilding second would let the template and the value being returned disagree. Cf. #591.

That width is a ceiling of the bit length over eight, and it is written as one. math.ceil(value.bit_length() // 8) is not a ceiling at all: math.ceil() of an int is that int, so the // has already floored the quotient and the outer call does nothing. Every value whose bit length is not an exact multiple of eight would be sized one octet short – 256 at one octet, 65536 at two, and 1 itself at zero – which int.to_bytes() and struct.pack() both refuse. See GitHub issue #599.

A value post_process() returned for octets whose bits outside bit_length were not what packing writes there carries those bits (see _outside_bits()), and they are written back as captured, so pack(unpack(b)) == b holds for every b. Only a field of the same length, bit length, sign and byte order as the one that captured them honours them; any other field, and any other value – one a caller built, or the result of arithmetic on a parsed one, which is a plain int – is truncated to bit_length bits. See GitHub issue #1488.

post_process(value, packet)[source]

Process field value after parsing (unpacked).

Parameters:
Return type:

int

Returns:

Processed field value.

Notes

Masking against self._bit_mask yields the unsigned pattern, so a signed field maps it back into its signed range afterwards, mirroring pre_process(). A resolved signed field therefore decodes ffffffff as -1 rather than 4294967295. See GitHub issue #1274.

The value is the low bit_length bits, but the octets hold more. When the bits outside it are not what pre_process() would write there for this value – zeros, or for a negative signed value the sign extension – they are captured but uninterpreted, and the value records them (see _with_outside_bits()) so that packing it writes them back. Otherwise the value is a plain int. See GitHub issue #1488.

pcapkit.corekit.fields.numbers._rebuild_unregistered_member(namespace, value, name, attrs)[source]

Rebuild the member EnumField._unregistered_member() returned.

This is what pickle and copy reconstruct through, in place of the value lookup Enum.__reduce_ex__ would otherwise have reduced the member to. It is a module-level function rather than a method so that every pickle protocol can name it: protocols below 4 cannot reference a callable nested inside a class.

Parameters:
  • namespace (Type[IntEnum] | Type[aenum.IntEnum]) – The registry class to rebuild the member as an instance of.

  • value (Any) – The member’s _value_.

  • name (str) – The member’s _name_.

  • attrs (dict[str, Any]) – The extra attributes the member carried.

Return type:

Any

Returns:

A member equal to the original and, like it, absent from every one of namespace’s lookup tables – rebuilding goes back through EnumField._unregistered_member() and never through namespace.__new__, so it cannot register anything either.

Removed in version 1.6.0: pcapkit.corekit.fields.numbers._reduce_unregistered_member, with no alias; pcapkit.utilities.pickle.reduce_to() installs the reduction it built (#2714).

class pcapkit.corekit.fields.numbers._CapturedInt[source]

Bases: int

An int that also records the bits outside its field’s bit_length as they were captured.

It equals, hashes and renders as the plain int it holds, and any arithmetic on it yields a plain int, which is what lets a value a caller derives from a parsed one keep a plain int’s truncating semantics. See GitHub issue #1488.

pcapkit.corekit.fields.numbers._outside_bits(value, field)[source]

Return the captured bits value records outside field’s bit_length, or None.

Parameters:
  • value (Any) – Field value.

  • field (NumberField) – The field packing it.

Return type:

int | None

Returns:

The bits, in place (not shifted down), if value was captured by a field of the same length, bit length, sign and byte order as field; None otherwise, so that any other field packs it exactly as it would the plain value.

pcapkit.corekit.fields.numbers._with_outside_bits(value, record)[source]

Return value recording record as its captured bits outside bit_length.

Parameters:
Return type:

int

Returns:

A _CapturedInt equal to value.

Type Variables

pcapkit.corekit.fields.numbers._T: int