tlv8 v0.1.0 TLV8

A small library that decodes and encodes TLV8 according to Apple’s specifications. It is intended to be compatible with TLV8 data structures used by HomeKit.

  • Encodes a list of type & value pairs into binary
  • Decodes binary into a list of type & value pairs
  • Automatically handles values longer than 255 bytes by splitting them into fragments

This TLV8 library is written by Charles Gutjahr, but was inspired by elixir_tlv. That library implements the ASN.1 BER-TLV format, a format that is somewhat similar to the Apple TLV8 format but is sufficiently different for that library to be unsuitable for working with Apple TLV8.

Licensed under the MIT license, see the LICENSE file for details.

Summary

Types

t()

Represents a type and value pair, a single item in an Apple TLV8 structure. TLV8 binary data may contain one or more of these items

Functions

Decodes the given binary TLV8 data, returning a list of all the items found (as TLV8 type & value pairs). The decoder will recursively extract all the items in the binary data until the data is exhausted

Encodes the given single TLV8 item or list of TLV8 items, and returns it in Apple TLV8 binary format

Types

t :: %TLV8{type: integer, value: binary}

Represents a type and value pair, a single item in an Apple TLV8 structure. TLV8 binary data may contain one or more of these items.

The type must be an integer between 0 and 255. Specifying a value outside this range will cause encoding to fail.

Note that the ‘L’ in TLV8, the length, is not included because it is calculated automatically during encoding and so does not need to be manually specified.

Functions

decode(tlv8)

Specs

decode(binary) :: [TLV8.t | :invalid_tlv8]

Decodes the given binary TLV8 data, returning a list of all the items found (as TLV8 type & value pairs). The decoder will recursively extract all the items in the binary data until the data is exhausted.

If invalid data is found, the decoder will return a list containing as many valid TLV8 type & value pairs as possible, then return the atom :invalid_tlv8 and stop. If the binary data cannot be parsed at all a list containing a single :invalid_tlv8 will be returned.

Examples

# Decoding binary data containing a single TLV8
iex> TLV8.decode(<<0xFF, 0x02, 0x03, 0x04>>)
[%TLV8{type: 255, value: <<3, 4>>}]

# Decoding binary data containing multiple TLV8s
iex> TLV8.decode(<<0x06, 0x01, 0x03, 0x01, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f>>)
[%TLV8{type: 6, value: <<3>>}, %TLV8{type: 1, value: "hello"}]

# Invalid TLV8
iex> TLV8.decode(<<0x80, 0x02, 0x00>>)
[:invalid_tlv8]
encode(tlv8)

Specs

encode(TLV8.t | [TLV8.t]) :: binary | :invalid_tlv8

Encodes the given single TLV8 item or list of TLV8 items, and returns it in Apple TLV8 binary format.

If any of the items given for encoding contain an invalid type, the encoder will return the atom :invalid_tlv8.

Examples

# Encoding a single TLV8
iex> TLV8.encode(%TLV8{type: 0xFF, value: <<0x03, 0x04>>})
<<0xFF, 0x02, 0x03, 0x04>>

# Encoding multiple TLV8s
iex> TLV8.encode([%TLV8{type: 0x06, value: <<0x03>>}, %TLV8{type: 1, value: "hello"}])
<<0x06, 0x01, 0x03, 0x01, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f>>

# Encoding an invalid TLV8 type
iex> TLV8.encode([%TLV8{type: 0x00, value: <<>>}, %TLV8{type: 0x100, value: <<0x00>>}])
:invalid_tlv8