tlv

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 10, 2020 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package tlv provides functionality to map Go structures to TLV encoded data and vice versa.

The mapping is done based on TLV templates. A 'Template' object is bound explicitly to a Go struct type (not the object value of that type). For a Template to be constructed, struct type fields must be annotated with tags, which provide mapping instructions (see (Template).Parse() for available annotations).

A Template is an immutable object and thus may be constructed once and be used thought out the program's lifetime (see 'templates' package for template registry).

Index

Constants

View Source
const (
	// HeaderFlag16 is mask for 16bit flag.
	HeaderFlag16 = HeaderMask(0x80)
	// HeaderFlagN is mask for Non-Critical flag.
	HeaderFlagN = HeaderMask(0x40)
	// HeaderFlagF is mask for Forward Unknown flag.
	HeaderFlagF = HeaderMask(0x20)
	// HeaderTypeMask is mask for type in the first header byte.
	HeaderTypeMask = HeaderMask(0x1f)
)
View Source
const (
	// MaxValueLength is the maximum size of the TLV value.
	MaxValueLength = 0xffff
	// MaxHeaderSize is the maximum size of the TLV header.
	MaxHeaderSize = 4
	// MaxBufferSize is the maximum size of the buffer needed to store any TLV.
	MaxBufferSize = MaxHeaderSize + MaxValueLength
	// MaxTagValue is the maximum size of the TLV tag value.
	MaxTagValue = 0x1fff
)
View Source
const (
	IUnknown  = templateIndex(-4) // Index unknown.
	IWhatever = templateIndex(-3) // Index can be anything.
	IFirst    = templateIndex(-2) // Must be first element.
	ILast     = templateIndex(-1) // Must be last element.
	IBase     = templateIndex(0)  // Index >= IBase is a concrete element position.

	Count0_1  = templateCount(-3) // Zero or one occurrences.
	Count0_N  = templateCount(-2) // Zero to many occurrences.
	Count1_N  = templateCount(-1) // One to many occurrences.
	CountBase = templateCount(0)  // Count >= CountBase is concrete count value.

	GroupNone = templateGroup(-1)

	VTImprint      = templateType(-1)  // Value (of struct field) must be *hash.Imprint.
	VTInt          = templateType(-2)  // Value (of struct field) must be *uint64.
	VTNested       = templateType(-3)  // Value (of struct field) must be *<struct>.
	VTUtf8         = templateType(-4)  // Value (of struct field) must be *string.
	VTbin          = templateType(-5)  // Value (of struct field) must be *[]byte.
	VTTlvObj       = templateType(-6)  // Value (of struct field) must be *<struct, implements TlvObj>.
	VTNestedTlvObj = templateType(-7)  // Value (of struct field) must be *<struct, implements TlvObj>.
	VTBaseTlv      = templateType(-8)  // Value (of struct field) must be *tlv.Tlc.
	VTUnknown      = templateType(-9)  // Unknown value type.
	VTInt8         = templateType(-10) // Value (of struct field) must be *uint64.
	VTContext      = templateType(-11) // Value (of struct field) must be *<something>.

)

Variables

This section is empty.

Functions

func IsConsistent

func IsConsistent(b []byte) bool

IsConsistent verifies whether the input stream contains a complete TLV structure.

func Marshal

func Marshal(v interface{}) ([]byte, error)

Marshal returns the binary TLV encoding of v.

Marshal traverses the value v recursively. If an encountered value implements the TlvObj interface and is not a nil pointer, Marshal calls its ToTlv method to produce TLV.

Marshal uses default type-dependent encodings as described in (Template).Parse.

func Unmarshal

func Unmarshal(data []byte, v interface{}) error

Unmarshal parses the TLV-encoded data and stores the result in the value pointed to by v.

Unmarshal uses the inverse of the encodings that Marshal uses (meaning only the value part).

Types

type Constructor

type Constructor func(*tlv) error

Constructor is constructor for TLV. See ConstructEmpty, ConstructFromObject, ConstructFromReader and ConstructFromSlice.

func ConstructEmpty

func ConstructEmpty(tag uint16, nc bool, fu bool) Constructor

ConstructEmpty is an option for constructing an empty TLV with initialized header values. For setting a value see (Tlv).SetValue().

func ConstructFromObject

func ConstructFromObject(v interface{}, templateInput *Template) Constructor

ConstructFromObject is an option for constructing TLV structure by traversing the value v recursively.

Note that the value v must point to an existing object that is bound to provided template, otherwise the output is undefined.

func ConstructFromReader

func ConstructFromReader(r io.Reader) Constructor

ConstructFromReader is an option for constructing TLV object from TLV binary stream.

func ConstructFromSlice

func ConstructFromSlice(b []byte) Constructor

ConstructFromSlice is an option for constructing TLV object from TLV binary slice.

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder keeps the TLV serialization state.

Serialization of TLV structures is performed from the most inner structure up to the root TLV.

func NewEncoder

func NewEncoder() (*Encoder, error)

NewEncoder creates memory buffer ready to store serialized TLV.

func (*Encoder) Bytes

func (e *Encoder) Bytes() []byte

Bytes returns current serialized state of the encoder.

func (*Encoder) PrependBinary

func (e *Encoder) PrependBinary(bin []byte) (uint64, error)

PrependBinary function serializes binary slice as big-endian beginning from position towards smaller indexes.

func (*Encoder) PrependHeader

func (e *Encoder) PrependHeader(tag uint16, isNonCritical, isForwardUnknown bool, valueLen uint64) (uint64, error)

PrependHeader function serializes TLV header with given parameters as big-endian beginning from position towards smaller indexes.

func (*Encoder) PrependUint64

func (e *Encoder) PrependUint64(value uint64) (uint64, error)

PrependUint64 function serializes uint64 as big-endian beginning from position towards smaller indexes.

func (*Encoder) PrependUint64E

func (e *Encoder) PrependUint64E(value uint64) (uint64, error)

PrependUint64E function serializes uint64 as big-endian beginning from position towards smaller indexes. When value is 0, TLV is built without a value.

func (*Encoder) PrependUint8

func (e *Encoder) PrependUint8(value uint64) (uint64, error)

PrependUint8 function serializes uint64 as big-endian beginning from position towards smaller indexes. Note that input is still uint64 but its size is limited with 1 byte.

func (*Encoder) PrependUint8E

func (e *Encoder) PrependUint8E(value uint64) (uint64, error)

PrependUint8E function serializes uint64 as big-endian beginning from position towards smaller indexes. Note that input is still uint64 but its size is limited with 1 byte. When value is 0, TLV is built without a value.

func (*Encoder) PrependUtf8

func (e *Encoder) PrependUtf8(str string) (uint64, error)

PrependUtf8 function serializes utf8 NUL terminated string as big-endian beginning from position towards smaller indexes.

type HeaderMask

type HeaderMask byte

HeaderMask holds mask values for different bits in TLV header.

type Template

type Template struct {
	// contains filtered or unexported fields
}

Template is used to convert binary stream into TLV and Go struct. That process can also be reversed where a Go structure is converted back into TLV encoded binary stream. TLV Template is generated using reflection and as it is immutable object, TLV Template is only generated once and can be reused in multiple goroutines. Note that after generation, Template uses reflection only slightly, thus not slowing it down.

To create a new empty TLV Template, see function NewTemplate. In order to bind newly created TLV Template with a struct, see function Parse.

func NewTemplate

func NewTemplate(tags ...uint16) (*Template, error)

NewTemplate is a function that creates an empty nested TLV Template with TLV tag(s).

func (*Template) IsMatchingTag

func (template *Template) IsMatchingTag(tag uint16) bool

IsMatchingTag checks if TLV tag is matching with the template.

func (*Template) Parse

func (template *Template) Parse(t reflect.Type) error

Parse is a function that derives a TLV Template for a struct from its reflection.Type. In order to parse TLV Template for a struct, an empty TLV Template with value type VTNested must be created. Secondly, the struct must contain struct field tags describing how each struct field is related to TLV and what kind of type the fields should contain. To improve error handling, the type is not determined by reflection automatically but the real type and user given type must match.

Possible struct field tags to bind struct field with TLV:

tlv:"<TLV type>, bin | int | int8 | imp | nstd | nstd+tlvobj | tlvobj | utf8, [C], [I], [G], [!G].., [&G].., [N], [F], [E]"
where:
  <TLV type>       - TLV type value in hex (e.g 1a).
  bin              - Field is *[]byte or *[][]byte.
  int              - Field is *uint64 or *[]uint64.
  int8             - Field is *uint64 or *[]uint64.
  imp              - Field is *hash.Imprint or *[]hash.Imprint.
  nstd             - Field is *<some struct> or *[]*<some struct>. Note that list contains POINTERS!
  nstd+tlvobj      - Field is *<some struct> or *[]*<some struct>. Note that list contains POINTERS and <some struct>
                     MUST implement TlvObject interface!
  tlvobj           - Field is *<some struct> or *[]*<some struct>. Note that list contains POINTERS and <some struct>
                     MUST implement TlvObject interface!
  utf8             - Field is utf8 *string or *[]string.
  C                - Expected count. C0_1 (default), C0_N, C1_N or C<num> (e.g. C5).
                     Option is Group dependant (see description of option 'G'). Meaning that if a group number is
                     applied, the count number is relevant only within that Group.
  I                - Expected position. IW (any position, default), IF (first), IL (last) or I<num> (e.g. I5).
  G                - Field belongs to a group. GNone (no group, default), G<num> (e.g. G0).
  !G               - Conflicting groups !G<num> (e.g. !G0 indicates that this field can not coexist with fields belonging
                     to group G0).
  &G               - Dependency groups &G<num> (e.g. &G0 indicates that if this field contains a value, the fields
                     belonging to group G0 must also have a value).
  N                - Non-Critical TLV.
  F                - Forward unknown (valid with N).
  E                - Permit usage of empty values (e.g integer 0 has no value part.)

tlv:"basetlv"      - Field must be *tlv.Tlv. During TLV to object this field is going to store the base TLV of the
                     struct itself.

tlv:"context,name" - Field must be pointer to something and name must verify its type for error handling (for *dummy
                     name must be 'dummy').

Usage example:

type nestedStruct struct {
   msg            *string       `tlv:"10,utf8"`
   unrelatedField uint8
}

type example struct {
   suffix         *[]bin        `tlv:"1,bin,IF"`
   id             *uint64       `tlv:"2,int"`
   value          *nestedStruct `tlv:"2,nstd"`
   prefix         *[]bin        `tlv:"4,bin,IL"`
   basetlv        *tlv.Tlv      `tlv:"basetlv"`
}

t := reflect.TypeOf(example)
template,_ := NewTemplate(VTNested, 0x2)
err := template.Parse(t)

func (*Template) SetPath

func (template *Template) SetPath(path string) error

SetPath is setter for Template path.

func (*Template) String

func (template *Template) String() string

type Tlv

type Tlv struct {
	NonCritical    bool   // If set, this TLV is non-critical.
	ForwardUnknown bool   // If set together with NonCritical, this TLV may be skipped by receiver.
	Is16           bool   // If set, this TLV is 16bit.
	Tag            uint16 // TLV type.
	Nested         []*Tlv // List of nested elements.
	Raw            []byte // Raw slice holds entire TLV structure.
	// contains filtered or unexported fields
}

TLV holds Type-Length-Value encoded data. Entire object is held in single byte array that can be accessed via TLV structure.

func NewTlv

func NewTlv(constructor Constructor) (*Tlv, error)

NewTlv is a constructor for a TLV object.

func (*Tlv) Binary

func (t *Tlv) Binary() ([]byte, error)

Binary is getter for TLV value.

func (*Tlv) Extract

func (t *Tlv) Extract(path ...uint16) (*Tlv, error)

Extract returns TLV by path.

func (*Tlv) Imprint

func (t *Tlv) Imprint() ([]byte, error)

Imprint is getter for hash imprint value. If imprint format is invalid, error is returned.

func (*Tlv) Length

func (t *Tlv) Length() int

Length returns the size of the TLV in bytes (header size + value length). The value length can be obtained via the slice (Tlv).value.

func (*Tlv) ParseNested

func (t *Tlv) ParseNested(tmpl *Template) error

ParseNested parses TLV value part with given Template. When parsing is complete, list of nested TLVs should be under input TLV.

func (*Tlv) SetValue

func (t *Tlv) SetValue(value []byte) error

SetValue sets the TLV value. Note that it will also affect the TLV header according the value length.

See (Tlv).NewTlv option ConstructEmpty for initializing a parent TLV object.

See Marshal for serializing object state into binary TLV value.

func (*Tlv) String

func (t *Tlv) String() string

String implements Stringer interface.

func (*Tlv) ToObject

func (t *Tlv) ToObject(v interface{}, templateInput *Template, ctx unsafe.Pointer) error

ToObject decodes structured TLV object (see (Tlv).ParseNested()) and stores the result into value v.

Note that the value v must point to an existing object that is bound to provided template, otherwise the output is undefined.

func (*Tlv) Uint64

func (t *Tlv) Uint64() (uint64, error)

Uint64 is getter for uint64. If TLV is empty or TLV value is larger than 8 bits, error is returned.

func (*Tlv) Uint64E

func (t *Tlv) Uint64E() (uint64, error)

Uint64E is getter for uint64. If TLV is empty, 0 is returned. If TLV value is larger than 8 bits, error is returned.

func (*Tlv) Uint8

func (t *Tlv) Uint8() (uint64, error)

Uint8 is getter for uint8. If TLV is empty or TLV value is larger than 1 bit, error is returned.

func (*Tlv) Uint8E

func (t *Tlv) Uint8E() (uint64, error)

Uint8E is getter for uint8. If TLV is empty, 0 is returned. If TLV value is larger than 1 bit, error is returned.

func (*Tlv) Utf8

func (t *Tlv) Utf8() (string, error)

Utf8 is getter for string. TLV value must end with 0 octet that is left out from returned string. If TLV is empty, error is returned.

func (*Tlv) Utf8E

func (t *Tlv) Utf8E() (string, error)

Utf8E is getter for string. TLV value must end with 0 octet that is left out from returned string. If TLV is empty, empty string is returned.

func (*Tlv) Value

func (t *Tlv) Value() []byte

Value returns the value of the TLV. If the receiver is nil, a nil slice is returned.

type TlvObj

type TlvObj interface {
	// FromTlv function configures existing object with the data retrieved from input TLV.
	FromTlv(*Tlv) error

	// ToTlv functions encodes existing object as TLV. Function is provided by buffer which must be filled from highest
	// index to the lowest as TLV serialization must start from the deepest TLV. Note that TLV is still encoded in
	// big-endian.
	//
	// Example:
	//
	// ToTlv gets input buffer that is a slice from a larger structure. Input extBuf is from position 0 to x. TLV is
	// serialized from position y to x. Entire structure is located from y to n.
	//
	// index : i=0                                  i=y                  i=x                   i=n
	// extBuf: [        UNUSED EMPTY BUFFER        ][   type:len:value   ][   PREVIOUS TLVs   ]
	ToTlv(*Encoder) (*Tlv, error)
}

TlvObj is interface that provides custom functionality to get object from TLV, or to encode object as TLV. This interface is used by functions (Tlv).ToObject and by TLV constructor ConstructFromObject.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL