protocoldataunits
ProtocolDataUnits python tools, Encoders and decoders for Protocol Data Units.
Science Score: 44.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
✓CITATION.cff file
Found CITATION.cff file -
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (13.3%) to scientific vocabulary
Keywords
Repository
ProtocolDataUnits python tools, Encoders and decoders for Protocol Data Units.
Basic Info
- Host: GitHub
- Owner: patel999jay
- License: mit
- Language: Python
- Default Branch: main
- Homepage: https://protocoldataunits.readthedocs.io/en/latest/?badge=latest
- Size: 1.1 MB
Statistics
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 1
- Releases: 0
Topics
Metadata Files
README.md
ProtocolDataUnits
ProtocolDataUnits is a Python toolset for encoding and decoding Protocol Data Units (PDUs). It is inspired by ProtocolDataUnits.jl by Dr. Mandar Chitre, ARL.
Installation
You can install ProtocolDataUnits from PyPI using:
bash
pip install ProtocolDataUnits
If you want to install it from the local source (for development or testing), use:
bash
pip install .
🔧 Command-Line Interface (CLI) Usage
After installation, you can quickly test the functionality using the built-in demo CLI tool:
bash
pdu-demo
This runs a collection of predefined PDU encoding/decoding examples showcasing:
- Basic field types (e.g., uint8, float, double)
- Fixed-length and length-prefixed strings
- Variable-length arrays
- Nested PDUs and pdu_fragment
- JSON serialization and deserialization
- Compression and decompression support
This is a great way to validate the installation and explore the library’s features interactively.
Features
ProtocolDataUnits is a Python toolset for encoding and decoding Protocol Data Units (PDUs). It includes the following features:
- Base PDU Definition: Define the structure and format of your PDUs.
- PDU Encoding/Decoding: Encode and decode PDUs with various field types.
- Nested PDU / PDU_FRAGMENT Support: Supports PDUs within PDUs, allowing for complex data structures.
- CRC32 Checksum: Automatically compute and validate CRC32 checksums for data integrity.
- Field Encoding/Decoding: Supports a variety of field types including integers, floats, strings, and arrays.
- Byte Order Conversion: Flexibly handle big-endian and little-endian byte orders.
- Metadata Storage: Store additional metadata within PDUs.
- Stream Writing/Reading: Efficiently write and read PDUs to and from streams.
- Variable Length Encoding/Decoding: Handle fields with variable length data.
- Pretty Printing of PDUs: Generate human-readable representations of PDUs.
- PDU Equality based on Fields: Compare PDUs based on their field values.
- Serialization and Deserialization: Serialize PDU definitions to JSON and deserialize them back to PDU objects.
Usage
Creating PDU Formats
You can create PDU formats using the user-friendly API, defining the structure, encoding data into binary format, and decoding it back into structured data.
```python from ProtocolDataUnits.pdu import createpduformat, PDU
Create a simple PDU format with uint8, float, and double fields
mypduformat = createpduformat( 24, 'big', # Total length: 24 bytes, big-endian order ('uint8', 'type'), # 1 byte ('float', 'value1'), # 4 bytes ('double', 'value2') # 8 bytes )
Encode data into binary format
encodedbytes = mypduformat.encode({'type': 7, 'value1': 3.14, 'value2': 6.28}) print(f"Encoded Bytes: {encodedbytes}")
Decode binary data back into structured format
decodeddata = mypduformat.decode(encodedbytes) print(f"Decoded Data: {decoded_data}") ```
Working with Nested PDUs
Nested PDUs allow you to embed one PDU structure within another, enabling more complex data structures.
```python
Define a nested PDU format
nestedpdu = createpduformat( 8, 'big', # Length: 8 bytes, big-endian order ('uint8', 'nestedtype'), # 1 byte ('uint8', 'nested_value') # 1 byte )
Define the main PDU format containing the nested PDU
mainpdu = createpduformat( 16, 'big', # Length: 16 bytes, big-endian order ('uint8', 'type'), # 1 byte ('pdufragment', 'nested', nested_pdu) # Nested PDU takes up 8 bytes )
Encode data with nested PDU
encodedbytes = mainpdu.encode({'type': 7, 'nested': {'nestedtype': 1, 'nestedvalue': 2}}) print(f"Encoded Bytes: {encoded_bytes}")
Decode data with nested PDU
decodeddata = mainpdu.decode(encodedbytes) print(f"Decoded Data: {decodeddata}") ```
Serialization and Deserialization
You can serialize a PDU's structure to JSON, allowing you to save and reload PDU definitions, making it easy to share PDU formats or store them for later use.
```python
Create a complex PDU with various field types
mypdu = PDU().length(68).order('big').uint8('type').float('value1').double('value2').fixedstring('fixedstr', 10).lengthprefixedstring('lengthstr').variablelengtharray('array', 'uint8').padding(0xff)
Encode data into the PDU format
encodedbytes = mypdu.encode({'type': 7, 'value1': 3.14, 'value2': 6.28, 'fixedstr': 'hello', 'lengthstr': 'dynamic string', 'array': [1, 2, 3, 4, 5]}, compress=True) print(f"Encoded Bytes: {encoded_bytes}")
Decode the PDU back into structured data
decodeddata = mypdu.decode(encodedbytes, decompress=True) print(f"Decoded Data: {decodeddata}")
Serialize the PDU definition to JSON
jsonstr = mypdu.tojson() print(f"Serialized PDU to JSON: {jsonstr}")
Deserialize the PDU from JSON
newpdu = PDU.fromjson(jsonstr) print(f"Deserialized PDU from JSON: {newpdu.to_json()}")
Encode and decode using the deserialized PDU
encodedbytesnew = newpdu.encode({'type': 7, 'value1': 3.14, 'value2': 6.28, 'fixedstr': 'hello', 'lengthstr': 'dynamic string', 'array': [1, 2, 3, 4, 5]}, compress=True) print(f"Encoded Bytes (new PDU): {encodedbytes_new}")
decodeddatanew = newpdu.decode(encodedbytesnew, decompress=True) print(f"Decoded Data (new PDU): {decodeddata_new}") ```
Advanced Example: API Usage
```python
Create a PDU format with various fields using the API
mypduformat = createpduformat( 48, 'big', # Length: 48 bytes, big-endian order ('uint8', 'type'), ('float', 'value1'), ('double', 'value2'), ('fixedstring', 'fixedstr', 10), ('lengthprefixedstring', 'lengthstr'), ('variablelength_array', 'array', 'uint8'), ('padding', 0xff) )
Nested PDU example
nestedpdu = createpduformat( 8, 'big', ('uint8', 'nestedtype'), ('uint8', 'nested_value') )
mainpdu = createpduformat( 16, 'big', ('uint8', 'type'), ('pdufragment', 'nested', nested_pdu) )
Encode data
encodedbytes = mainpdu.encode({'type': 7, 'nested': {'nestedtype': 1, 'nestedvalue': 2}}) print(f"Encoded Bytes: {encoded_bytes}")
Decode data
decodeddata = mainpdu.decode(encodedbytes) print(f"Decoded Data: {decodeddata}") ```
Notes
- Compression and Decompression: Using
compress=Trueinencode()will compress the resulting byte array with zlib, reducing size. Usedecompress=Trueindecode()to decode compressed data. - Serialization: Convert your PDU definitions to JSON for easy saving and sharing of structures.
- Flexible Field Types: Supports integers, floats, fixed-length strings, length-prefixed strings, arrays, nested PDUs, and more.
Data Encoding Details
The ProtocolDataUnits library provides support for various types of data, including fixed-length strings, length-prefixed strings, and variable-length arrays. Below is an explanation of how each of these types is encoded:
1. Fixed-Length Strings
A fixed-length string is encoded as a byte sequence of a specified length. If the string provided is shorter than the specified length, it is padded with null bytes (\x00). If the string is longer, it is truncated to fit the specified length.
- Field Definition:
fixed_string('name', length=10) - Example:
- Input:
"hello"(5 characters) - Length:
10 - Encoded:
b'hello\x00\x00\x00\x00\x00'(5 characters plus 5 null bytes) - If the input was
"helloworld!!!", onlyb'helloworld'(10 characters) would be encoded.
- Input:
2. Length-Prefixed Strings
A length-prefixed string is encoded as an integer representing the length of the string, followed by the string data itself. The length is typically stored as a 4-byte unsigned integer (uint32), allowing strings up to 2^32 - 1 bytes.
- Field Definition:
length_prefixed_string('name') - Example:
- Input:
"dynamic string" - Encoded:
b'\x0e\x00\x00\x00dynamic string' b'\x0e\x00\x00\x00'represents the length14(0x0e in hexadecimal) as a 4-byte integer.b'dynamic string'is the actual string data.
- Input:
This encoding ensures that the length of the string is known during decoding, making it possible to handle strings of varying lengths.
3. Variable-Length Arrays
A variable-length array is encoded similarly to length-prefixed strings. The array is prefixed with a 4-byte integer (uint32) that indicates the number of elements in the array, followed by the serialized form of each element.
- Field Definition:
variable_length_array('name', element_type='uint8') - Example:
- Input:
[1, 2, 3, 4, 5](an array ofuint8) - Encoded:
b'\x05\x00\x00\x00\x01\x02\x03\x04\x05' b'\x05\x00\x00\x00'represents the length5as a 4-byte integer.b'\x01\x02\x03\x04\x05'contains the array elements encoded asuint8values.
- Input:
Each element of the array is encoded according to the specified element_type. For instance, if the array type is uint16, each element would occupy 2 bytes.
4. Padding
Padding is used to align data to a specific byte boundary or to ensure that the PDU reaches a predefined length. Padding bytes are usually filled with a specific value (often zero or a user-defined value).
- Field Definition:
padding(value=0xff) - Example:
- If 4 bytes of padding are needed, the encoded value might be
b'\xff\xff\xff\xff'whenvalue=0xff.
- If 4 bytes of padding are needed, the encoded value might be
Summary Table
| Field Type | Prefix/Length | Data Format | Example (in bytes) |
|-----------------------------|---------------|--------------------------------------|--------------------------------------------------|
| Fixed-Length String | None | Data padded or truncated to length | b'hello\x00\x00\x00\x00\x00' (length 10) |
| Length-Prefixed String | 4 bytes | Length + Data | b'\x0e\x00\x00\x00dynamic string' (length 14) |
| Variable-Length Array | 4 bytes | Length + Element Data | b'\x05\x00\x00\x00\x01\x02\x03\x04\x05' |
| Padding | None | Repeated value bytes | b'\xff\xff\xff\xff' |
Additional Notes
- The use of length prefixes allows the decoder to know precisely how many bytes to read for a string or an array, making variable-length fields easier to handle.
- For large arrays or strings, consider the impact of storing length prefixes as
uint32(4 bytes), as they slightly increase the size of the encoded data. - Padding ensures data alignment but may add extra bytes to the encoded PDU.
CITATION
- If you use ProtocolDataUnits for your research, please cite it as below:
BibTex @software{Patel_ProtocolDataUnits_2023, author = {Patel, Jay and Chitre, Mandar}, license = {MIT}, month = oct, title = {{ProtocolDataUnits}}, url = {https://github.com/patel999jay/ProtocolDataUnits}, version = {1.0.0}, year = {2023} }
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
License
References:
Owner
- Name: Jay Patel
- Login: patel999jay
- Kind: user
- Location: Halifax, Canada
- Company: Dalhousie University
- Website: https://patel999jay.github.io/
- Twitter: jay_patel888
- Repositories: 2
- Profile: https://github.com/patel999jay
Citation (CITATION.cff)
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
title: "ProtocolDataUnits"
abstract: "A Python package for encoding and decoding Protocol Data Units (PDUs). This repository provides functionality to process PDUs efficiently, supporting various formats and custom structures."
authors:
- family-names: "Patel"
given-names: "Jay"
affiliation: "Dalhousie University, NS, Canada"
orcid: "https://orcid.org/0000-0003-0811-3977"
- family-names: "Chitre"
given-names: "Mandar"
affiliation: "National University of Singapore, Singapore"
orcid: "https://orcid.org/0000-0001-6243-7871"
version: "1.0.0"
date-released: 2023-10-06
url: "https://github.com/patel999jay/ProtocolDataUnits"
repository-code: "https://github.com/patel999jay/ProtocolDataUnits"
license: "MIT"
GitHub Events
Total
- Release event: 1
- Delete event: 1
- Push event: 22
- Pull request event: 5
- Pull request review event: 5
- Pull request review comment event: 5
- Create event: 2
Last Year
- Release event: 1
- Delete event: 1
- Push event: 22
- Pull request event: 5
- Pull request review event: 5
- Pull request review comment event: 5
- Create event: 2
Issues and Pull Requests
Last synced: 6 months ago
All Time
- Total issues: 0
- Total pull requests: 1
- Average time to close issues: N/A
- Average time to close pull requests: 1 minute
- Total issue authors: 0
- Total pull request authors: 1
- Average comments per issue: 0
- Average comments per pull request: 0.0
- Merged pull requests: 1
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 0
- Pull requests: 1
- Average time to close issues: N/A
- Average time to close pull requests: 1 minute
- Issue authors: 0
- Pull request authors: 1
- Average comments per issue: 0
- Average comments per pull request: 0.0
- Merged pull requests: 1
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
Pull Request Authors
- patel999jay (3)
Top Labels
Issue Labels
Pull Request Labels
Dependencies
- sphinx ==7.1.2
- sphinx-rtd-theme ==1.3.0rc1
- Any *
- requests *
