3.2.2.4. Unnamed#
Unnamed provides a different take on the same C-union idea as Union:
instead of a whole struct where every field shares memory, Unnamed
is a single field whose value may be one of several possible types, all overlaid on the
same fixed-size window of bytes. It is declared with a subscription syntax rather than a
decorator:
>>> @struct
... class Format:
... value: Unnamed[uint32, CString(4)]
...
Unlike union(), an Unnamed value does
not eagerly decode every alternative. The fixed-size byte window is read once, immediately,
like any other field - but each alternative is only decoded (and then cached) the first time
it is actually requested, via value[i] or the shorthand attribute form
value._i:
>>> obj = unpack(Format, b"\x01\x00\x00\x00ABC\x00")
>>> obj.value[0]
1
>>> obj.value._1
'ABC'
Sizing#
By default, the field’s size is the largest of its member types’ sizes - every member
must therefore have a statically-known, fixed __size__. An explicit size (an
int or a context lambda) can be supplied via .sized(...) to override this,
which is required if any member has a greedy or otherwise unsized __size__:
>>> @struct
... class Format:
... n: uint16
... value: Unnamed[uint32, uint16].sized(this.n)
...
Access#
value[i]/value._i- decode (or return the cached) memberi. Negative indices are supported.value[i:j]- returns a plaintupleof the decoded members in that range.len(value)- the number of members.Iterating a value decodes and yields every member in order.
An Unnamed value can also be constructed directly, without a
prior unpack - this is how you produce a value for packing from scratch:
>>> Unnamed() # nothing assigned yet
Unnamed()
>>> Unnamed(1, 2, 3) # positional: fills index 0, 1, 2
Unnamed(1, 2, 3)
>>> Unnamed(_3=0xBEEF) # keyword: only index 3 is set
Unnamed(?, ?, ?, 48879)
Positional arguments fill indices left to right starting at 0; keyword arguments named
_<index> (e.g. _0, _3) set an arbitrary index directly.
For more information and examples, see Unnamed.