fpack is a simple message (de)serializer created for fun and educational purpose. fpack hasn't been widely deployed, so use it at your own risk.
- python >= 3.7
pip install fpack
git clone https://github.com/frankurcrazy/fpack
cd fpack && python setup.py install
The following shows an example that uses fpack to declare and pack/unpack a message.
fpack supports primitive types:
- Uint8
- Uint16
- Uint32
- Uint64
- Int8
- Int16
- Int32
- Int64
- Bytes
- String
import fpack
# Declare a Hello message, with MsgID (`Uint8`) and Greeting (`String`) field.
class Hello(fpack.Message):
Fields = [
fpack.field_factory("MsgID", fpack.Uint8),
fpack.field_factory("Greeting", fpack.String),
]
>>> helloMsg = Hello()
>>> helloMsg.MsgID = 100
>>> helloMsg.Greetings = "Helloworld!"
>>> helloMsg
<Hello MsgID=100 Greetings="Helloworld!">
>>> helloMsg.pack()
b'd\x00\x0bHelloworld!'
Message deserialization can be done by calling class method from_bytes
,
or by calling instance method unpack
Decode with class method from_bytes
:
# using the byte-stream from previous example
>>> decodedMsg, decodedLength = Hello.from_bytes(b'd\x00\x0bHelloworld!')
>>> decodedMsg
<Hello MsgID=100 Greetings=Helloworld!>
Decode with instance method unpack
:
>>> decodedMsg = Hello()
>>> decodedMsg.unpack(b'd\x00\x0bHelloworld!')
16
>>> decodedMsg
<Hello MsgID=100 Greetings="Helloworld!">
Nested message is supported.
Declaring an nested message:
import fpack
class MailHeader(fpack.Message):
Fields = [
fpack.field_factory("Subject", fpack.String),
fpack.field_factory("From", fpack.String),
fpack.field_factory("To", fpack.String),
]
class MailBody(fpack.Message):
Fields = [
fpack.field_factory("Body", fpack.String),
fpack.field_factory("Signature", fpack.String),
]
class Mail(fpack.Message):
Fields = [
fpack.field_factory("Header", MailHeader),
fpack.field_factory("Body", MailBody),
]
>>> mail = Mail()
>>> header = mail.Header
>>> header.Subject = "this is a mail"
>>> header.From = "John Doe"
>>> header.To = "Jane Doe"
>>> body = mail.Body
>>> body.Text = "mail body"
>>> body.Signature = "by John doe"
>>> mail
<Mail Header=<Header Subject="this is a mail" From="John Doe" To="Jane Doe"> Body=<Body Text="mail body" Signature="by John doe">>
>>> mail.pack()
b'\x00\x0ethis is a mail\x00\x08John Doe\x00\x08Jane Doe\x00\tmail body\x00\x0bby John doe'
Array field is supported and can be created via array_field_factory(name, type)
.
import fpack
class Item(fpack.Message):
Fields = [
fpack.field_factory("Name", fpack.String),
fpack.field_factory("Price", fpack.Uint32),
]
class Catalog(fpack.Message):
Fields = [
fpack.field_factory("CatalogID", fpack.Uint8),
fpack.array_field_factory("Items", Item),
]
items = [
Item(Name="Camera", Price=10),
Item(Name="Computer", Price=12),
Item(Name="Dildo", Price=5),
]
>>> catalog = Catalog(CatalogID=1, Items=items)
<Catalog CatalogID=1 Items=<Items length=3 items=[<Item Name="Camera" Price=10>,<Item Name="Computer" Price=12>,<Item Name="Dildo" Price=5>]>>
>>> catalog.pack()
b'\x01\x00\x03\x00\x06Camera\x00\x00\x00\n\x00\x08Computer\x00\x00\x00\x0c\x00\x05Dildo\x00\x00\x00\x05'
BSD