Package: easyprotocol
EasyProtocolIntroductionA library for quick prototyping protocol parsing in python. Not the fastest, not the most efficient, not the coolest, but hopefully the easiest to modify and prototype with.Quick StartInstallingFor now you have to install from source, this will be on pypi soon.Current Methodgitclonehttps://github.com/joeferg425/EasyProtocol.git.cdEasyProtocol
python-mpipinstall.Future, better methodpython-mpipinstalleasyprotocolExample 1 - Making a Parser From a List of FieldsDemo CodeLets parse something like the following.NameBit CountData Typeid88-bit intdata count1616-bit unsigned intdata88-bit unsigned intFixed frame definition. Nothing fancy."""Define your parser using simple python classes and familiar types."""fromeasyprotocol.baseimportParseFieldList,hexfromeasyprotocol.fieldsimportInt8Field,UInt8Field,UInt16Field# Make an instance of the modified list type and add your fields as the list items.exampleParser=ParseFieldList(# give the parser a namename="ExampleParser1",# define your fields in orderdefault=[# give each field a name, some standard field types are already defined.Int8Field(name="id"),UInt16Field(name="count"),UInt8Field(name="data"),],)# Some example data bytes to parsedata=b"\x01\x00\x01\x80"print(f"input bytes:\t{data!r}")print(f"input hex:\t{hex(data)}\n")# Parse the bytesexampleParser.parse(data=data)# Print the parsed data to see what we gotprint(f"parsed:\t{exampleParser}")print(f"bytes:\t{bytes(exampleParser)!r}")print(f"hex:\t{exampleParser.hex_value}\n")# Make a new frame from known data to send somewhere (like a socket)exampleParser[0].value=3exampleParser.value=[3,257,127]exampleParser.value=[3,257,127]print(f"parsed:\t{exampleParser}")print(f"bytes:\t{bytes(exampleParser)!r}")print(f"hex:\t{exampleParser.hex_value}\n")# You can access parsed elements of a ParseList by numeric index.forchildinexampleParser.children.values():print(f'{child.name}:\t{child.value}\t"{child.string_value}"')print()# Wait, I don't really like hexadecimalexampleParser.string_format="{}"forchildinexampleParser.children.values():child.string_format="{}"# Print the values againexampleParser[0].value=3exampleParser.value=[3,257,127]exampleParser.value=[3,257,127]print(f"parsed:\t{exampleParser}")print(f"bytes:\t{bytes(exampleParser)!r}")print(f"hex:\t{exampleParser.hex_value}\n")forchildinexampleParser.children.values():print(f'{child.name}:\t{child.value}\t"{child.string_value}"')Outputinputbytes:b'\x01\x00\x01\x80'inputhex:01000180parsed:ExampleParser1:[id:1,count:0001(hex),data:80(hex)]bytes:b'\x01\x00\x01\x80'hex:01000180parsed:ExampleParser1:[id:3,count:0101(hex),data:7F(hex)]bytes:b'\x03\x01\x01\x7f'hex:0301017F

id:3"3"count:257"0101(hex)"data:127"7F(hex)"parsed:ExampleParser1:[id:3,count:257,data:127]bytes:b'\x03\x01\x01\x7f'hex:0301017F

id:3"3"count:257"257"data:127"127"```Example 2 - Making a Parser from a Dictionary of FieldsDemo CodeLets parse something like the following.NameBit CountData Typeid88-bit unsigned intcount1616-bit unsigned intdata array88-bit unsigned int(s)Variable Frame size, handles a variable length array of uint8 chunks."""Define your parser using simple python classes and familiar types."""fromtypingimportcastfromeasyprotocol.baseimportParseFieldDict,ParseFieldList,hexfromeasyprotocol.fieldsimportInt8Field,ParseArrayField,UInt8Field,UInt16Field# you can define your field classes before using them in a parser.ident=Int8Field(name="id")count=UInt16Field(name="count",# Let's modify the display of the field valuestring_format="{}data items",)data_array=ParseArrayField(name="data",count=count,array_item_class=UInt8Field,array_item_default=0,)# Make an instance of the modified list type and add your fields as the list items.exampleParser=ParseFieldDict(# give the parser a namename="ExampleParser",# define your fields in orderdefault=[# give each field a name, some standard types are defined for you.ident,count,data_array,],)# Some example data bytes to parsedata=b"\x01\x00\x01\x80"print(f"input bytes:\t{data!r}\n")print(f"input hex:\t{hex(data)}\n")# Parse the bytesexampleParser.parse(data=data)# Print the parsed data to see what we gotprint(f"parsed:\t{exampleParser}")print(f"hex:\t{hex(exampleParser)}\n")# Make a new frame from known data to send somewhere (like a socket)exampleParser["id"].value=3exampleParser["count"].value=2exampleParser["data"].value=[127,UInt8Field(name="new data",default=15),]print(f"parsed:\t{exampleParser}")print(f"hex:\t{hex(exampleParser)}\n")# You can access parsed elements of a ParseDict by name.idField=exampleParser[ident.name]dataCountField=exampleParser[count.name]dataField=cast(ParseFieldList,exampleParser[data_array.name])# The ArrayField is a list type, so children are accessed by numeric index.forchildinexampleParser.values():print(f"{child.name}:\t{child.value}\t\t{child.bits_str}")Outputinputbytes:b'\x01\x00\x01\x80'inputhex:01000180parsed:ExampleParser:{id:1,count:1dataitems,data:[#0: 80(hex)]}hex:01000180parsed:ExampleParser:{id:3,count:2dataitems,data:[#0: 7F(hex), #1: 0F(hex)]}hex:0300027F0F

id:300000011:<b
count:20000000000000010:<b
data:[<UInt8Field>#0: 7F(hex), <UInt8Field> #1: 0F(hex)]            0111111100001111:<b```