Instruct is a Python library for marshalling objects in a (more) declarative way, especially suited for packing/unpacking protocols such as networking, SCSI, etc.
It is based on ctypes view of defining a struct as a class, and on Construct's method of declaring var-sized fields.
Instruct provides two different philosophies on marshalling:
What makes Instruct different from ctypes?
What makes Instruct different from Construct?
Some of the things you gain by using Instruct:
__repr__
implementation.Let's see how we declare an IPv4 packet with Instruct's Buffer. For this example we assume:
So here's the IPv4 packet representation:
from instruct.buffer import *
class IPv4Packet(Buffer):
version = be_int_field(where=bytes_ref[0].bits[0:4], set_before_pack=4)
internet_header_length = be_int_field(where=bytes_ref[0].bits[4:8], set_before_pack=self._calc_header_length)
dscp = be_int_field(where=bytes_ref[1].bits[0:6])
ecn = be_int_field(where=bytes_ref[1].bits[6:8])
total_length = be_int_field(where=bytes_ref[2:4],
set_before_pack=lambda self: self.byte_offset_after('data'))
identification = be_int_field(where=bytes_ref[4:6])
flags = be_int_field(where=bytes_ref[6].bits[0:3])
fragment_offset = be_int_field(where=bytes_ref[6:7].bits[3:16])
time_to_live = be_int_field(where=bytes_ref[8])
protocol = be_int_field(where=bytes_ref[9])
header_checksum = be_int_field(where=bytes_ref[10:12]) # FIXME
source_ip_address = list_field(where=bytes_ref[12:16], n=4, type=uint8)
destination_ip_address = list_field(where=bytes_ref[16:20], n=4, type=uint8)
options = list_field(where_when_pack=bytes_ref[20:],
where_when_unpack=bytes_ref[20:20 + internet_header_length * ]
Struct
is now deprecated and where possible should be migrated to using the new Buffer
.
Run the following:
easy_install -U infi.projector
projector devenv build
Python 3 support is experimental at this stage. Most of the functions that expect a non-textual string in Python 2 must receive a parameter from the type bytes
in Python 3.
Objects that could have been serialized in Python 2 by calling str(o) have to be serialized in Python 3 by calling their to_bytes
method, as it's forbidden to return bytes
from __str__ in Python 3.