Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

uttlv

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

uttlv

Python Library for TLV objects

  • 0.7.1
  • PyPI
  • Socket score

Maintainers
1

TLV Python Parser - Version 0.7.1

A Tag-Length-Value (also known as Type-Length-Value) is an encoding scheme used for many protocols.

The tag is fixed in size (can be set from 1 to 4 bytes). The length is automatically determined by how many bytes it would take to represent the size of the value by default, but could be set to a fixed size (from 1 to 4 bytes). The value field is of variable size.

The fields are:

  • Tag: An alphanumeric code that represents the kind of field the object represents;
  • Length: Size of the value field (in bytes);
  • Value: Variable-sized series of bytes which contains data for this field object.

Advantages of using TLV:

  • Sequences are usually easy to parse;
  • Unknown tags or elements can be skipped or ignored, so new versions can be added without a problem;
  • Elements can be placed in any order;
  • New elements can be created without breaking the protocol itself or the parsing function.

For more information, you can see: https://en.wikipedia.org/wiki/Type-length-value

Installation

You can install directly from PyPI:

  pip install uttlv

Or download the source code and install using pip:

  pip install .

How to use

To start using this package, just import the package and create an object

  from uttlv import TLV

  # Create object
  t = TLV()

To add a tag to object, do it like a dict value:

  # A tag of int value
  t[0x01] = 10
  # A tag of string value
  t[0x02] = 'test'
  # A tag of an array of bytes
  t[0x03] = bytes([1, 2, 3])
  # Or another TLV object
  another_one = TLV()
  another_one[0x05] = 234
  t[0x04] = another_one

A tag can only be int, str, bytes or a TLV itself. Any other type will raise a TypeError exception. If a tag is inserted and another object with same tag value already exists on the object, the tag will be overriden with the new value.

To get the underlying array, just call to_byte_array() method:

  arr = t.to_byte_array()
  print('TLV:', arr)

Parse

To parse an array, just call the method parse_array():

  # create object
  t = TLV()
  # parse from object
  data = bytes([0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A])
  t.parse_array(data)

Pretty print

If you call tree(), the object will create a string with a tree-like structure to print:

  from prtlv import TLV

  # Create object
  t = TLV()
  # Add value
  t[0x01] = 10
  # Print it
  print('Value:\n', t.tree())
  ## <output>
  ## Value: 
  ## 1: 10
  ##

Tag map

You can also add a dictionary to map a tag to its underline class type, so it's showed as correct type instead of a bytearray.

The dictionary must have all keys as the tag values and its respective values as the class type of the tag:

  config = {
      0x01: {TLV.Config.Type: int, TLV.Config.Name: 'NUM_POINTS'},
      0x02: {TLV.Config.Type: int, TLV.Config.Name: 'IDLE_PERIOD'},
      0x03: {TLV.Config.Type: str, TLV.Config.Name: 'NAME'},
      0x04: {TLV.Config.Type: str, TLV.Config.Name: 'CITY'},
      0x05: {TLV.Config.Type: bytes, TLV.Config.Name: 'VERSION'},
      0x06: {TLV.Config.Type: bytes, TLV.Config.Name: 'DATA'},
      0x07: {TLV.Config.Type: TLV, TLV.Config.Name: 'RELATED'},
      0x08: {TLV.Config.Type: TLV, TLV.Config.Name: 'COMMENT'},
      0x09: {TLV.Config.Type: TLV, TLV.Config.Name: 'Empty'}
  }

  # Set global default map
  TLV.set_global_tag_map(config)

  # Set tag map for a specific instance (this will override the global setting)
  t = TLV()
  t.set_local_tag_map(config)

For now, only 'int', 'str', 'bytes', 'TLV', and a dictionary are accepted as valid classes. Any other class will raise AttributeError.

If a tag map is configured, one can use the tag name to access its value:

 t = TLV()
 t['NUM_POINTS'] = 10
 print(t['NUM_POINTS'])

Nested tag maps can be configured by replacing the configured type with another configuration dictionary:

  config = {
    0x01: {TLV.Config.Name: 'FIRST_NEST', TLV.Config.Type: {
      0x01: {TLV.Config.Name: 'SECOND_NEST', TLV.Config.Type: {
        0x01: {TLV.Config.Name: 'THIRD_NEST', TLV.Config.Type: int}
      }}
    }}
  }

And also can print it with all tag names instead of values:

 t.tree(use_names=True)
 ## <output>
 ## NUM_POINTS: 10

You can access also the tags directly:

 t = TLV()
 t['NUM_POINTS'] = 10
 print(t.NUM_POINTS)

By default, a field defined as type str in the tag map would be encoded or decoded as utf-8. The encoder can be replaced to use utf16, utf32 or ascii by setting it in

 uttlv.tlv.ALLOWED_TYPES[str] = uttlv.tlv.encoder.Utf16Encoder

or

 uttlv.tlv.ALLOWED_TYPES[str] = uttlv.tlv.encoder.Utf32Encoder

or

 uttlv.tlv.ALLOWED_TYPES[str] = uttlv.tlv.encoder.AsciiEncoder

respectively.

Iterator

You can iterate through the available tags inside a TLV object by using iter():

t = TLV()
t.parse_array(bytes(command_data))

for command in t:
  pass

Keywords

FAQs


Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc