restruct

package module
v0.0.0-...-93d5b55 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2017 License: ISC Imports: 11 Imported by: 0

README

restruct Build Status codecov.io godoc.org

restruct is a library for reading and writing binary data in Go. Similar to lunixbochs struc and encoding/binary, this library reads data based on the layout of structures and, like struc, based on what is contained in struct tags.

To install Restruct, use the following command:

go get gopkg.in/restruct.v1

restruct aims to provide a clean, flexible, robust implementation of struct packing. In the future, through fast-path optimizations and code generation, it also aims to be quick, but it is currently very slow.

Heads up! This code works best on Go 1.5 and above, because it makes use of the reflect.ArrayOf function added in Go 1.5. See "Arrays" below.

Status

  • As of writing, coverage is hovering around 95%, but more thorough testing is always useful and desirable.
  • Unpacking and packing are fully functional.
  • More optimizations are probably possible.

Arrays

Restruct supports array types without limitations on all versions of Go it supports. However, in Go 1.4 and below, there are limitations on overriding with array types in struct tags because Go 1.4 and below do not provide the reflect.ArrayOf function necessary to dynamically get an array type.

When compiled on Go 1.4 and below, Restruct will use a workaround to support a limited number of array types in struct tags. You can specify the following kinds of arrays by default:

  • uint8/byte arrays ranging from 0...128 in length.
  • arrays of any other primitive ranging from 0...32 in length.
  • any array of array from 1...4 lengths of type uint8, uint16, uint32, uint64, float32, or float64.

In addition, you can statically register more array types by calling the RegisterArrayType function (this is a no-op on Go 1.5.)

Example

package main

import (
	"encoding/binary"
	"io/ioutil"
	"os"

	"gopkg.in/restruct.v1"
)

type Record struct {
	Message string `struct:[128]byte`
}

type Container struct {
	Version   int `struct:int32`
	NumRecord int `struct:int32,sizeof=Records`
	Records   []Record
}

func main() {
	var c Container

	file, _ := os.Open("records")
	defer file.Close()
	data, _ := ioutil.ReadAll(file)

	restruct.Unpack(data, binary.LittleEndian, &c)
}

Documentation

Overview

Package restruct implements packing and unpacking of raw binary formats.

Structures can be created with struct tags annotating the on-disk or in-memory layout of the structure, using the "struct" struct tag, like so:

struct {
	Length int `struct:"int32,sizeof=Packets"`
	Packets []struct{
		Source    string    `struct:"[16]byte"`
		Timestamp int       `struct:"int32,big"`
		Data      [256]byte `struct:"skip=8"`
	}
}

To unpack data in memory to this structure, simply use Unpack with a byte slice:

msg := Message{}
restruct.Unpack(data, binary.LittleEndian, &msg)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Pack

func Pack(order binary.ByteOrder, v interface{}) (data []byte, err error)

Pack writes data from a datastructure into a byteslice.

Two types of values are directly supported here: Packers and structs. You can pass them by value or by pointer.

Each structure is serialized in the same way it would be deserialized with Unpack. See Unpack documentation for the struct tag format.

func RegisterArrayType

func RegisterArrayType(array interface{})

RegisterArrayType registers an array type for use with struct tags. This function is only necessary on Go 1.4 and below, which do not provide reflect.ArrayOf. This function is goroutine safe and idempotent (i.e., calling it multiple times with the same value is perfectly safe.) If you require Go 1.5 or above, you can safely use any array type in your struct tags without using this function.

func Unpack

func Unpack(data []byte, order binary.ByteOrder, v interface{}) (err error)

Unpack reads data from a byteslice into a value.

Two types of values are directly supported here: Unpackers and structs. You can pass them by value or by pointer, although it is an error if Restruct is unable to set a value because it is unaddressable.

For structs, each field will be read sequentially based on a straightforward interpretation of the type. For example, an int32 will be read as a 32-bit signed integer, taking 4 bytes of memory. Structures and arrays are laid out flat with no padding or metadata.

Unexported fields are ignored, except for fields named _ - those fields will be treated purely as padding. Padding will not be preserved through packing and unpacking.

The behavior of deserialization can be customized using struct tags. The following struct tag syntax is supported:

`struct:"[flags...]"`

Flags are comma-separated keys. The following are available:

type            A bare type name, e.g. int32 or []string.

sizeof=[Field]  Specifies that the field should be treated as a count of
                the number of elements in Field.

skip=[Count]    Skips Count bytes before the field. You can use this to
                e.g. emulate C structure alignment.

big,msb         Specifies big endian byte order. When applied to structs,
                this will apply to all fields under the struct.

little,lsb      Specifies little endian byte order. When applied to structs,
                this will apply to all fields under the struct.

Types

type Packer

type Packer interface {
	Sizer
	Pack(buf []byte, order binary.ByteOrder) ([]byte, error)
}

Packer is a type capable of packing a native value into a binary representation. The Pack function is expected to overwrite a number of bytes in buf then return a slice of the remaining buffer. Note that you must also implement SizeOf, and returning an incorrect SizeOf will cause the encoder to crash. The SizeOf should be equal to the number of bytes consumed from the buffer slice in Pack. You may use a pointer receiver even if the type is used by value.

type Sizer

type Sizer interface {
	SizeOf() int
}

Sizer is a type which has a defined size in binary. The SizeOf function returns how many bytes the type will consume in memory. This is used during encoding for allocation and therefore must equal the exact number of bytes the encoded form needs. You may use a pointer receiver even if the type is used by value.

type Unpacker

type Unpacker interface {
	Unpack(buf []byte, order binary.ByteOrder) ([]byte, error)
}

Unpacker is a type capable of unpacking a binary representation of itself into a native representation. The Unpack function is expected to consume a number of bytes from the buffer, then return a slice of the remaining bytes in the buffer. You may use a pointer receiver even if the type is used by value.

Jump to

Keyboard shortcuts

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