Skip to main content

A library for quick protocol prototyping and parsing.

Project description

EasyProtocol

Introduction

A 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 Start

Installing

For now you have to install from source, this will be on pypi soon.

  • Current Method
git clone https://github.com/joeferg425/EasyProtocol.git .
cd EasyProtocol
python -m pip install .
  • Future, better method
python -m pip install easyprotocol

Example 1 - Making a Parser From a List of Fields

  • Demo Code

    Lets parse something like the following.

    Name Bit Count Data Type
    id 8 8-bit int
    data count 16 16-bit unsigned int
    data 8 8-bit unsigned int

    Fixed frame definition. Nothing fancy.

    """Define your parser using simple python classes and familiar types."""
    from easyprotocol.base import ParseFieldList, hex
    from easyprotocol.fields import Int8Field, UInt8Field, UInt16Field
    
    # Make an instance of the modified list type and add your fields as the list items.
    exampleParser = ParseFieldList(
        # give the parser a name
        name="ExampleParser1",
        # define your fields in order
        default=[
            # 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 parse
    data = b"\x01\x00\x01\x80"
    print(f"input bytes:\t{data!r}")
    print(f"input hex:\t{hex(data)}\n")
    
    # Parse the bytes
    exampleParser.parse(data=data)
    
    # Print the parsed data to see what we got
    print(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 = 3
    exampleParser.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.
    for child in exampleParser.children.values():
        print(f'{child.name}:\t{child.value}\t"{child.string_value}"')
    print()
    
    # Wait, I don't really like hexadecimal
    exampleParser.string_format = "{}"
    for child in exampleParser.children.values():
        child.string_format = "{}"
    
    # Print the values again
    exampleParser[0].value = 3
    exampleParser.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")
    for child in exampleParser.children.values():
        print(f'{child.name}:\t{child.value}\t"{child.string_value}"')
    
  • Output

    input bytes:    b'\x01\x00\x01\x80'
    input hex:      01 00 01 80
    
    parsed: ExampleParser1: [id: 1, count: 0001(hex), data: 80(hex)]
    bytes:  b'\x01\x00\x01\x80'
    hex:    01 00 01 80
    
    parsed: ExampleParser1: [id: 3, count: 0101(hex), data: 7F(hex)]
    bytes:  b'\x03\x01\x01\x7f'
    hex:    03 01 01 7F
    
    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:    03 01 01 7F
    
    id:     3       "3"
    count:  257     "257"
    data:   127     "127"
        ```
    

Example 2 - Making a Parser from a Dictionary of Fields

  • Demo Code

    Lets parse something like the following.

    Name Bit Count Data Type
    id 8 8-bit unsigned int
    count 16 16-bit unsigned int
    data array 8 8-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."""
    from typing import cast
    
    from easyprotocol.base import ParseFieldDict, ParseFieldList, hex
    from easyprotocol.fields import Int8Field, 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 value
        string_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 name
        name="ExampleParser",
        # define your fields in order
        default=[
            # give each field a name, some standard types are defined for you.
            ident,
            count,
            data_array,
        ],
    )
    
    # Some example data bytes to parse
    data = b"\x01\x00\x01\x80"
    print(f"input bytes:\t{data!r}\n")
    print(f"input hex:\t{hex(data)}\n")
    
    # Parse the bytes
    exampleParser.parse(data=data)
    # Print the parsed data to see what we got
    print(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 = 3
    exampleParser["count"].value = 2
    exampleParser["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.
    for child in exampleParser.values():
        print(f"{child.name}:\t{child.value}\t\t{child.bits_str}")
    
  • Output

    input bytes:    b'\x01\x00\x01\x80'
    
    input hex:      01 00 01 80
    
    parsed: ExampleParser: {id: 1, count: 1 data items, data: [#0: 80(hex)]}
    hex:    01 00 01 80
    
    parsed: ExampleParser: {id: 3, count: 2 data items, data: [#0: 7F(hex), #1: 0F(hex)]}
    hex:    03 00 02 7F 0F
    
    id:     3               00000011:<b
    count:  2               0000000000000010:<b
    data:   [<UInt8Field> #0: 7F(hex), <UInt8Field> #1: 0F(hex)]            0111111100001111:<b
        ```
    

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

easyprotocol-0.0.3.tar.gz (26.9 kB view hashes)

Uploaded Source

Built Distribution

easyprotocol-0.0.3-py3-none-any.whl (44.9 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page