Special Types

Constant

You can make any value a constant using oser.Constant().

oser.Constant() raises a ValueError if the current value does not match the desired value.

oser.Constant(*args: ByteType | BitType, **kwargs: Any) ByteType | BitType

Wrapper to make any OSER type or class a constant.

Parameters:
  • *args (tuple) – the first positional argument is the class that will be made constant. All other parameters are passed to the __init__ of the first positional argument.

  • **kwargs – keyword parameters are passed to the __init__ of the first positional argument.

Usage:

>>> from oser import ByteStruct, Constant, ULInt8, String, to_hex

>>> c = Constant(ULInt8, 23)  # constant scalar
>>> print(c.introspect())
   0 \x17  23 (ULInt8)

>>> binary = c.encode()
>>> print(to_hex(binary))
   0
\x17
>>> c.decode(b"\x00")
ValueError: Constant value not matched: expected value: 23, decoded value: 0

>>> class Foo(ByteStruct):  # constant scalar nested in a ByteStruct
...     def __init__(self):
...         super(Foo, self).__init__()
...         self.c = Constant(ULInt8, 23)
...
>>> f = Foo()
>>> print(f.introspect())
   -    -  Foo():
   0 \x17      c: 23 (ULInt8)

>>> binary = f.encode()
>>> print(to_hex(binary))
   0
\x17
>>> f.decode(b"\x00")
ValueError: Constant value not matched: expected value: 23, decoded value: 0

>>> c = Constant(String, length=10, value=b"abcdefghij")  # constant String
>>> print(c.introspect())
   -    -  String():
   0 \x61      'a'
   1 \x62      'b'
   2 \x63      'c'
   3 \x64      'd'
   4 \x65      'e'
   5 \x66      'f'
   6 \x67      'g'
   7 \x68      'h'
   8 \x69      'i'
   9 \x6a      'j'

>>> binary = c.encode()
>>> print(to_hex(binary))
   0|  1|  2|  3|  4|  5|  6|  7|  8|  9
\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A
>>> c.decode(b"\x61\x62\x63\x64\x65\x66\x67\x68\x69B")
ValueError: Constant value not matched: expected value: abcdefghij, decoded value: abcdefghiB

Google Protocol Buffers Adapter

Google Protocol Buffers can be used with an adapter. This way it is possible to create protocols that include messages using Google Protocol Buffers but can also be extended with a CRC for example.

class oser.ProtocolBuffersAdapter(instance: Any | None = None, length: Callable | int | None = None)

ProtocolBuffersAdapter builds a Google Protocol Buffers adapter.

Parameters:
  • instance=None – an instance of a Google Protocol Buffers class.

  • length=None – the length of the serialized data. If None the rest of the data is used so in most cases it should be a lambda expression. Look at the examples for more details.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

If length is None, decoding is done iterative starting with the full buffer and removing one last byte after another until the buffer can be decoded. The buffer must fit the decoded message in protobuf and must not be longer or shorter.

If decoding is not possible at all a DecodeException is raised.

It is recommended not to set length to None even if it works.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the encoded binary string.

Return type:

bytes

get() Any | None

Return the protocol buffers instance.

get_byte_size() int

Return the size in bytes.

get_size() int

Return the size in bytes.

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(instance: Any | None) None

Set the protocol buffers instance.

Parameters:

instance – the protocol buffers instance

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

set_length(length: Callable | int | None) None

Set the length.

Parameters:

length=None – states the string length. Can be a callable (e.g. lambda) or a scalar. If set to None the result is a null-terminated string. If set to an Integer the result is a fixed length string padded with padding. If set to a callable (lambda or function) the result is a fixed or variable length string padded with padding.

up() ByteStruct | BitStruct

Return the parent element.

The example uses the following proto file:

package tutorial;

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

message AddressBook {
  repeated Person person = 1;
}

Usage:

>>> from oser import ByteStruct, ProtocolBuffersAdapter, UBInt16, CRCB32, to_hex
>>> from tutorial_pb2 import Person

>>> class Data(ByteStruct):
...         def __init__(self):
...             super(Data, self).__init__()
...
...             self.payloadLength = UBInt16(0)
...             person = Person()
...             person.id = 1
...             person.name = "name"
...             person.PhoneNumber.number = 2
...             self.payload = ProtocolBuffersAdapter(object=person, length=lambda self: self.payloadLength.get())
...             self.crc = CRCB32(strict=True)
...
...         def encode(self, full_data="", context_data=""):#
...             self.payloadLength.set(len(self.payload.encode()))
...             #print("set length to", self.length.get())
...             return super(Data, self).encode()
...
>>> instance = Data()

>>> binary = instance.encode()
>>> print(instance)
Data():
    payloadLength: 8 (UBInt16)
    payload:
name
    crc: 3809365856 (CRCB32)

>>> print(instance.introspect())
   -    -  Data():
   0 \x00      payloadLength: 8 (UBInt16)
   1 \x08
   -    -      payload: ProtocolBuffersAdapter(Person):
   2 \x0a          '\n'
   3 \x04          '\x04'
   4 \x6e          'n'
   5 \x61          'a'
   6 \x6d          'm'
   7 \x65          'e'
   8 \x10          '\x10'
   9 \x01          '\x01'
  10 \xe3      crc: 3809365856 (CRCB32)
  11 \x0e
  12 \x4f
  13 \x60

>>> print(to_hex(binary))
   0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13
\x00\x08\x0A\x04\x6E\x61\x6D\x65\x10\x01\xE3\x0E\x4F\x60

>>> # alter data
... person = instance.payload.get()
>>> person.id = 123456789
>>> person.name = "another name"
>>> person.PhoneNumber.number = 1337

>>> binary = instance.encode()
>>> print(instance)
Data():
    payloadLength: 19 (UBInt16)
    payload:

another name���:
    crc: 3147422169 (CRCB32)

>>> print(instance.introspect())
   -    -  Data():
   0 \x00      payloadLength: 19 (UBInt16)
   1 \x13
   -    -      payload: ProtocolBuffersAdapter(Person):
   2 \x0a          '\n'
   3 \x0c          '\x0c'
   4 \x61          'a'
   5 \x6e          'n'
   6 \x6f          'o'
   7 \x74          't'
   8 \x68          'h'
   9 \x65          'e'
  10 \x72          'r'
  11 \x20          ' '
  12 \x6e          'n'
  13 \x61          'a'
  14 \x6d          'm'
  15 \x65          'e'
  16 \x10          '\x10'
  17 \x95          '\x95'
  18 \x9a          '\x9a'
  19 \xef          '\xef'
  20 \x3a          ':'
  21 \xbb      crc: 3147422169 (CRCB32)
  22 \x99
  23 \xd9
  24 \xd9

>>> print(to_hex(binary))
   0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23| 24
\x00\x13\x0A\x0C\x61\x6E\x6F\x74\x68\x65\x72\x20\x6E\x61\x6D\x65\x10\x95\x9A\xEF\x3A\xBB\x99\xD9\xD9

>>> bytes_decoded = instance.decode(b"\x00\x10\x0A\x0C\x48\x49\x4C\x53\x54\x45\x52\x20\x47\x6D\x62\x48\x10\x01\x0F\x5B\x58\x85")
>>> print(bytes_decoded)
22
>>> print(instance)
Data():
    payloadLength: 16 (UBInt16)
    payload:

HILSTER GmbH
    crc: 257644677 (CRCB32)

>>> print(instance.introspect())
   -    -  Data():
   0 \x00      payloadLength: 16 (UBInt16)
   1 \x10
   -    -      payload: ProtocolBuffersAdapter(Person):
   2 \x0a          '\n'
   3 \x0c          '\x0c'
   4 \x48          'H'
   5 \x49          'I'
   6 \x4c          'L'
   7 \x53          'S'
   8 \x54          'T'
   9 \x45          'E'
  10 \x52          'R'
  11 \x20          ' '
  12 \x47          'G'
  13 \x6d          'm'
  14 \x62          'b'
  15 \x48          'H'
  16 \x10          '\x10'
  17 \x01          '\x01'
  18 \x0f      crc: 257644677 (CRCB32)
  19 \x5b
  20 \x58
  21 \x85


>>> print("name:", instance.payload.get().name)
name: HILSTER GmbH

JSON Adapter

It is possible to serialize and deserialize JSON with OSER.

class oser.JSONAdapter(data: Any)

JSONAdapter builds a JSON serializer.

Parameters:

data=None – the data to be json-ized.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the encoded binary string.

Return type:

bytes

get() Any

Return the value.

Returns:

the value

get_byte_size() int

Return the size in bytes.

get_size() int

Return the size in bytes.

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: Any) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

set_length(length: Callable | int | None) None

Set the length.

Parameters:

length=None – states the string length. Can be a callable (e.g. lambda) or a scalar. If set to None the result is a null-terminated string. If set to an Integer the result is a fixed length string padded with padding. If set to a callable (lambda or function) the result is a fixed or variable length string padded with padding.

up() ByteStruct | BitStruct

Return the parent element.

Usage:

>>> from oser import JSONAdapter

>>> data = {
...     "list" : [ii for ii in range(3)],
...     "scalar" : 1337,
...     "string" : "test"
...     }

>>> j = JSONAdapter(data=data)
>>> print(j)
{'scalar': 1337, 'list': [0, 1, 2], 'string': 'test'}

>>> print(j.encode())
{"list":[0,1,2],"scalar":1337,"string":"test"}
>>> print(j.introspect())
   -    -  JSONAdapter():
   0 \x7b      '{'
   1 \x22      '"'
   2 \x6c      'l'
   3 \x69      'i'
   4 \x73      's'
   5 \x74      't'
   6 \x22      '"'
   7 \x3a      ':'
   8 \x5b      '['
   9 \x30      '0'
  10 \x2c      ','
  11 \x31      '1'
  12 \x2c      ','
  13 \x32      '2'
  14 \x5d      ']'
  15 \x2c      ','
  16 \x22      '"'
  17 \x73      's'
  18 \x63      'c'
  19 \x61      'a'
  20 \x6c      'l'
  21 \x61      'a'
  22 \x72      'r'
  23 \x22      '"'
  24 \x3a      ':'
  25 \x31      '1'
  26 \x33      '3'
  27 \x33      '3'
  28 \x37      '7'
  29 \x2c      ','
  30 \x22      '"'
  31 \x73      's'
  32 \x74      't'
  33 \x72      'r'
  34 \x69      'i'
  35 \x6e      'n'
  36 \x67      'g'
  37 \x22      '"'
  38 \x3a      ':'
  39 \x22      '"'
  40 \x74      't'
  41 \x65      'e'
  42 \x73      's'
  43 \x74      't'
  44 \x22      '"'
  45 \x7d      '}'
  46 \x00      '\x00'

>>> j2 = JSONAdapter()
>>> j2.decode(b"[1,2,3]\x00")
8
>>> print(j2)
[1, 2, 3]

>>> print(j2.get())
[1, 2, 3]
>>> print(type(j2.get()))
<type 'list'>
>>> j3 = JSONAdapter()
>>> j3.set([4,5,6])
>>> print(j3)

Regular Expression Match

If you need a oser.String that fulfills some constraints you can use oser.RegularExpressionMatch() to do this. oser.RegularExpressionMatch() expects a regular expression that is applied to the String`s value. A `RegularExpressionMismatchException is raised if the current value does not match the regular expression.

oser.RegularExpressionMatch(pattern: str | bytes, length: Callable | int | None = None, value: bytes | str = b'', padding: bytes | str = b'\x00') String

RegularExpressionMatch creates a oser.String matches a regular expression.

Parameters:
  • pattern – a regular expression pattern.

  • length – the length of the underlying string.

  • value="" – the initial value.

  • padding=b"" – padding character for the string when it is encoded.

Usage (only match numeric strings):

>>> from oser import ByteStruct, ULInt8, RegularExpressionMatch, to_hex

>>> class Foo(ByteStruct):
...     def __init__(self):
...         super(Foo, self).__init__()
...
...         self.length = ULInt8(10)
...         self.numbers = RegularExpressionMatch(pattern=r"^[0-9]*$", length=lambda self: self.length.get(),
                value=b"0123456789")
...
>>> f = Foo()
>>> print(f.introspect())
   -    -  Foo():
   0 \x0a      length: 10 (ULInt8)
   -    -      numbers: RegularExpressionMatch():
   1 \x30          '0'
   2 \x31          '1'
   3 \x32          '2'
   4 \x33          '3'
   5 \x34          '4'
   6 \x35          '5'
   7 \x36          '6'
   8 \x37          '7'
   9 \x38          '8'
  10 \x39          '9'

>>> binary = f.encode()
>>> print(to_hex(binary))
   0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10
\x0A\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39
>>> f.decode(b"\x0A\x30\x31\x32\x33\x34\x35\x36\x37\x38A")
oser.RegularExpressionMismatchException: Current value (012345678A) does not match regular expression (^[0-9]*$)

Repeat Until

Sometimes you have optional data in your data stream or you need to decode items until the end of a stream or until a stop condition is met. Then oser.Array might not be an option if you don’t know the number of items.

In this cases oser.RepeatUntil can help. In general it works like oser.Array but length is not a callable. For encoding you can set the items and the length and for decoding the length is determined dynamically while oser.RepeatUntil consumes items until stop_condition returns True, an exception is raised or the data stream ends.

class oser.RepeatUntil(length: int, stop_condition: Callable | bool | None, prototype: ByteStruct | BitStruct | ByteType | BitType, stop_on_exception: bool = False, args: Tuple | None = None, kwargs: Dict | None = None, values: List[ByteStruct | BitStruct | ByteType | BitType] | None = None)

RepeatUntil builds an array serializer with a variable length that is determined dynamically on decoding.

Parameters:
  • length – states the initial length

  • stop_condition – the stop condition called with context, data (the next bytes to be parsed), full_data (all data) and context_data the data within the current hierarchy. If stop_condition returns True decoding stops.

  • prototype – a class that is the prototype for values

  • stop_on_exception – if set to True a DecodeException is handled as a stop condition.

  • args=None – a tuple of positional arguments that are passed to prototype when it is instantiated when array size is extended. Note: don’t forget a leading comma when passing one value (1,) ((1) is an integer!).

  • kwargs=None – a dictionary of named arguments that are passed to prototype when it is instantiated when array size is extended.

  • values=None – the initial array values. Can be left empty. If empty the array is automatically resized with instances of prototype(*args, **kwargs).

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the encoded binary string.

Return type:

bytes

from_dict(data: Dict) None

Fill self with data.

Parameters:

data – data to be used to fill the calling instance.

fuzzing_iterator(copy: bool = False) Generator[Any, None, None]

The fuzzing iterator iterates over all combinations of set fuzzing values (oser.ByteType.set_fuzzing_values()). If no fuzzing values are set the current struct is yielded.

Parameters:

copy=False – if set to True the generated fuzzing values are deep copies of the original. Creating these deep copies is slow. If set to False the original struct is retruned and the generated value must be used immediately since the next generated overwrites the values on the same value.

Yields:

the fuzzing combinations.

get() RepeatUntil

Return the value.

get_byte_size() int

Return the current size in bytes.

get_size() int

Return the current size in bytes.

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set_length(length: int) None

Set the length.

Parameters:

length – the new length

to_dict() List[Dict[Any, Any]]

Return self as a dict()

up() ByteStruct | BitStruct

return parent element

Usage:

>>> from oser import ByteStruct, RepeatUntil, CRCB32, UBInt8, to_hex

>>> length = 3
>>> class Data(ByteStruct):
...     def __init__(self):
...         super(Data, self).__init__()
...         self.items = RepeatUntil(length,
...                         stop_condition=lambda ctx,
...                             data, full_data,
...                             context_data: len(data) <= 4,
...                         prototype=UBInt8,
...                         values=[UBInt8(ii) for ii in range(length)])
...         self.crc = CRCB32(strict=True)
...
>>> data = Data()
>>> data.items.set_length(20)  # resize
>>> for ii in range(20):
...     data.items[ii].set(ii)
...
>>> encoded = data.encode()
>>> print(to_hex(encoded))
   0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22| 23
\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x6D\xA9\x2B\x61
>>> print(data.introspect())
   -    -  Data():
   -    -      items: RepeatUntil():
   -    -      [
   0 \x00          @0: 0 (UBInt8)
   1 \x01          @1: 1 (UBInt8)
   2 \x02          @2: 2 (UBInt8)
   3 \x03          @3: 3 (UBInt8)
   4 \x04          @4: 4 (UBInt8)
   5 \x05          @5: 5 (UBInt8)
   6 \x06          @6: 6 (UBInt8)
   7 \x07          @7: 7 (UBInt8)
   8 \x08          @8: 8 (UBInt8)
   9 \x09          @9: 9 (UBInt8)
  10 \x0a          @10: 10 (UBInt8)
  11 \x0b          @11: 11 (UBInt8)
  12 \x0c          @12: 12 (UBInt8)
  13 \x0d          @13: 13 (UBInt8)
  14 \x0e          @14: 14 (UBInt8)
  15 \x0f          @15: 15 (UBInt8)
  16 \x10          @16: 16 (UBInt8)
  17 \x11          @17: 17 (UBInt8)
  18 \x12          @18: 18 (UBInt8)
  19 \x13          @19: 19 (UBInt8)
   -    -      ]
  20 \x6d      crc: 1839803233 (CRCB32)
  21 \xa9
  22 \x2b
  23 \x61

>>> b = b"\x00\x01\x02\x03\xC1\xE9\xBD\xED"
>>> data2 = Data()
>>> decoded = data2.decode(b)
>>> print(data2.introspect())
   -    -  Data():
   -    -      items: RepeatUntil():
   -    -      [
   0 \x00          @0: 0 (UBInt8)
   1 \x01          @1: 1 (UBInt8)
   2 \x02          @2: 2 (UBInt8)
   3 \x03          @3: 3 (UBInt8)
   -    -      ]
   4 \xc1      crc: 3253321197 (CRCB32)
   5 \xe9
   6 \xbd
   7 \xed

Lazy Initialization

Sometimes you need to speed up some things. You can use the oser.Lazy element to initialize an object on first demand. So if an object is never used it is never initialized saving memory and cpu time.

class oser.Lazy(cls: Type[ByteStruct | BitStruct | ByteType | BitType], *args: ByteStruct | BitStruct | ByteType | BitType, **kwargs: Any)

Lazy can be used to realize lazy-initialization automatically.

cls is instantiated on first access but not in __init__(). So if no access is done it will never be instantiated and will not occupy any memory and cpu time.

Parameters:
  • cls – the class to be instantiated.

  • *args – a tuple for positional arguments for cls.

  • **kwargs – a dict for named arguments for cls.

Usage:

>>> from oser import ByteStruct, ULInt8, Lazy

>>> class Foo(ByteStruct):
...     def __init__(self):
...         super(Foo, self).__init__()
...
...         self.a = Lazy(ULInt8, 2)
...
>>> foo = Foo()
>>> print(foo) # foo.a is now initialized
Foo():
    a: 2 (ULInt8)

BitMap

oser.BitMap is a bit type that allows you to easily add bits at a given position instead of calculating these positions manually. This makes it easier to implement a protocol with many status bits, etc.

Indexes can either be integers or tuples of byte and bit positions. Both types can be mixed. Every undefined bit position is filled with a oser.PaddingFlag that might by strict if the strict option is set to True.

Every name is converted to lowercase and every character that cannot be part of a class member is removed. Thus it is possible that the names are not unique. If names are not unique they are postfixed with the byte and the bit position. The postfixed members must be used to modify and read values.

Reserved bits are hidden when the instance is printed and are visible in introspection.

class oser.BitMap(length: int, values: Dict[int | Tuple[int, int], str] | None = None, strict: bool = False)

BitMap type that automatically generates oser.PaddingFlag() at undefined bit positions. Reserved bits are hidden in stringified output.

Parameters:
  • length (int) – the length in bits

  • values=None (dict) – dictionary with key: value where key is the bit index as integer or a tuple of (byte, bit)

  • strict=False (bool) – When True, non-specified values must be 0

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data (bytes) – the data buffer that is decoded.

  • full_data (bytes) – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data (bytes) – the binary data of the current context. The user normally does not need to supply this.

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data (bytes) – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data (bytes) – the binary data of the current context. The user normally does not need to supply this.

from_dict(data: Dict) None

Fill self with data.

Parameters:

data (dict) – data to be used to fill the calling instance.

fuzzing_iterator(copy: bool = False) Generator[Any, None, None]

The fuzzing iterator iterates over all combinations of set fuzzing values (oser.ByteType.set_fuzzing_values()). If no fuzzing values are set the current struct is yielded.

Parameters:

copy=False (bool) – if set to True the generated fuzzing values are deep copies of the original. Creating these deep copies is slow. If set to False the original struct is retruned and the generated value must be used immediately since the next generated overwrites the values on the same value.

Yields:

the fuzzing combinations.

get_byte_size() int

Return the size in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the size in bits.

Returns:

the length of the bit type in bits.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None (object) – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

to_dict() Dict

Return self as a dict()

up() ByteStruct | BitStruct

return parent element

Usage:

>>> import oser

>>> class StructWithIntegerIndexes(oser.BitStruct):
...     def __init__(self):
...         super(StructWithIntegerIndexes, self).__init__()
...
...         self.bitmap = oser.BitMap(8,
...                                   values={
...                                       0: "a",
...                                       1: "b",
...                                       2: "c"
...                                   })
...

>>> s = StructWithIntegerIndexes()
>>> s.bitmap.a.set(True)
>>> print(s)
StructWithIntegerIndexes():
    bitmap: BitMap():
        c: 0 (Flag)
        b: 0 (Flag)
        a: True (Flag)

>>> print(s.introspect())
   -    -  StructWithIntegerIndexes():
   -    -      bitmap: BitMap():
   0.7  0          reserved_0_7: False (PaddingFlag)
   0.6  0          reserved_0_6: False (PaddingFlag)
   0.5  0          reserved_0_5: False (PaddingFlag)
   0.4  0          reserved_0_4: False (PaddingFlag)
   0.3  0          reserved_0_3: False (PaddingFlag)
   0.2  0          c: 0 (Flag)
   0.1  0          b: 0 (Flag)
   0.0  1          a: True (Flag)



>>> class StructWithTupleIndexes(oser.BitStruct):
...     def __init__(self):
...         super(StructWithTupleIndexes, self).__init__()
...
...         self.bitmap = oser.BitMap(8,
...                                   values={
...                                       (0, 0): "a",
...                                       (0, 1): "b",
...                                       (0, 2): "c"
...                                   })
...

>>> s = StructWithTupleIndexes()
>>> s.bitmap.a.set(True)
>>> print(s)
StructWithTupleIndexes():
    bitmap: BitMap():
        c: 0 (Flag)
        b: 0 (Flag)
        a: True (Flag)

>>> print(s.introspect())
   -    -  StructWithTupleIndexes():
   -    -      bitmap: BitMap():
   0.7  0          reserved_0_7: False (PaddingFlag)
   0.6  0          reserved_0_6: False (PaddingFlag)
   0.5  0          reserved_0_5: False (PaddingFlag)
   0.4  0          reserved_0_4: False (PaddingFlag)
   0.3  0          reserved_0_3: False (PaddingFlag)
   0.2  0          c: 0 (Flag)
   0.1  0          b: 0 (Flag)
   0.0  1          a: True (Flag)



>>> class StructWithNonUniqueNames(oser.BitStruct):
...     def __init__(self):
...         super(StructWithNonUniqueNames, self).__init__()
...
...         self.bitmap = oser.BitMap(8,
...                                   values={
...                                       0: "foobar",
...                                       1: "foobar",
...                                   })
...

>>> s = StructWithNonUniqueNames()
>>> print(s)
StructWithNonUniqueNames():
    bitmap: BitMap():
        foobar_0_1: 0 (Flag)
        foobar_0_0: 0 (Flag)

>>> print(s.introspect())
   -    -  StructWithNonUniqueNames():
   -    -      bitmap: BitMap():
   0.7  0          reserved_0_7: False (PaddingFlag)
   0.6  0          reserved_0_6: False (PaddingFlag)
   0.5  0          reserved_0_5: False (PaddingFlag)
   0.4  0          reserved_0_4: False (PaddingFlag)
   0.3  0          reserved_0_3: False (PaddingFlag)
   0.2  0          reserved_0_2: False (PaddingFlag)
   0.1  0          foobar_0_1: 0 (Flag)
   0.0  0          foobar_0_0: 0 (Flag)

Modbus Types

oser includes special integer types for modbus applications.

UInt2143

class oser.UInt2143(value: int = 0, format: str | None = None)

Unsigned, 32-Bit integer with modbus endianness: little endian ordered registers with big endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

SInt2143

class oser.SInt2143(value: int = 0, format: str | None = None)

Signed, 32-Bit integer with modbus endianness: little endian ordered registers with big endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

UInt3412

class oser.UInt3412(value: int = 0, format: str | None = None)

Unsigned, 32-Bit integer with modbus endianness: big endian ordered registers with little endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

SInt3412

class oser.SInt3412(value: int = 0, format: str | None = None)

Signed, 32-Bit integer with modbus endianness: big endian ordered registers with little endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

UInt21436587

class oser.UInt21436587(value: int = 0, format: str | None = None)

Unsigned, 64-Bit integer with modbus endianness: little endian ordered registers with big endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

SInt21436587

class oser.SInt21436587(value: int = 0, format: str | None = None)

Signed, 64-Bit integer with modbus endianness: little endian ordered registers with big endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

UInt78563412

class oser.UInt78563412(value: int = 0, format: str | None = None)

Unsigned, 64-Bit integer with modbus endianness: big endian ordered registers with little endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

SInt78563412

class oser.SInt78563412(value: int = 0, format: str | None = None)

Signed, 64-Bit integer with modbus endianness: big endian ordered registers with little endian content.

Parameters:
  • value – the initial value.

  • format=None – Use “hex” to format values to hexadecimal. Use “bin” to format values to binary.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() int

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: int) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

Float3412

class oser.Float3412(value: float = 0.0)

Unsigned, 32-Bit float with modbus endianness: big endian ordered registers with little endian content.

Parameters:

value – float = 0.0: the initial value.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() float

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: float) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

Float2143

class oser.Float2143(value: float = 0.0)

Unsigned, 32-Bit float with modbus endianness: little endian ordered registers with big endian content.

Parameters:

value – float = 0.0: the initial value.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() float

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: float) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

Double78563412

class oser.Double78563412(value: float = 0.0)

Unsigned, 64-Bit double with modbus endianness: big endian ordered registers with little endian content.

Parameters:

value – float = 0.0: the initial value.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() float

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: float) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.

Double21436587

class oser.Double21436587(value: float = 0.0)

Unsigned, 64-Bit double with modbus endianness: little endian ordered registers with big endian content.

Parameters:

value – float = 0.0: the initial value.

decode(data: bytes, full_data: bytes = b'', context_data: bytes = b'') int

Decode a binary string and return the number of bytes that were decoded.

Parameters:
  • data – the data buffer that is decoded.

  • full_data – the binary data string until the part to be decoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

Returns:

the number of bytes that were decoded.

Return type:

int

encode(full_data: bytes = b'', context_data: bytes = b'') bytes

Return the encoded binary string.

Parameters:
  • full_data – the binary data string until the part to be encoded. The user normally does not need to supply this.

  • context_data – the binary data of the current context. The user normally does not need to supply this.

get() float

Return the value.

Returns:

the value.

get_byte_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

get_size() int

Return the length of the byte type in bytes.

Returns:

the length of the byte type in bytes.

Return type:

int

introspect(stop_at: ByteStruct | BitStruct | ByteType | BitType | None = None) str

Return the introspection representation of the object as a string.

Parameters:

stop_at=None – stop introspection at stop_at.

root() ByteStruct | BitStruct

return root element

set(value: float) None

Set the value.

Parameters:

value – the new value

set_fuzzing_values(values: Generator[Any, None, None] | List[Any] | None) None

Set fuzzing values.

Parameters:

values – the values used for fuzzing.

up() ByteStruct | BitStruct

Return the parent element.