pakparse

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2019 License: Apache-2.0 Imports: 15 Imported by: 0

README

pakparse

PAKPARSE IS NOT CONCURRENCY-SAFE

GoDoc

About

pakparse is a go package that parses packets out of byte streams. It supports fixed data patterns and variable length fields.

How it works

pakparse uses reflection to look at a given struct's fields and tags. From this, it builds a state machine for parsing these structs from a byte stream.

To Do

  • Support passing through discarded bytes
  • Document that pakparse:"-" will omit a field
  • Use count and len tags for slice fields
    • count indicates the expected number of values
    • len indicates the length of each value – also valid for arrays
    • Special case for []byte - use len as count
  • Document fast path cases
    • Fields that are arrays or slices of byte or uint8 use a fast path for setting. Fields of type X []byte can use this fast path. Fields of type []MyInt where type MyInt byte cannot use this fast path.

Documentation

Overview

Package pakparse parses packets out of byte streams.

Note

This is a work in progress. The API may change. It should be usable for any scenarios similar to those tested in pakparse_test.go.

Basics

This package has a lot of overlap with "encoding/binary", if your application can use that, it probably should.

This package supports finding known patterns in a binary stream, and variable length fields.

There are two main functions. New, which creates a parser based on an output channel of any struct type. And Run, which reads a channel of []byte and writes whole structs to the output channel.

Controlling the parser

The parser created by New is influenced by tags on your struct. New looks for the "pakparse" entry in a standard reflect.StructTag string, then looks at the internal entries. Valid entries are:

data

This field must exactly match the given data. data is a hex string beginning with '0x'. It can be larger than a uint64.

len

This field has this length in bytes, except when this field is a slice, where it means number of elements in the slice.

vlen

This field has a variable length in bytes found in an earlier field with given name.

maxlen

This variable length field cannot exceed given length in bytes.

endian

This field should be decoded with given byte order. Big endian is the default. Valid values are 'little', 'big'.

type ExampleVariablePacket struct {
	Magic   uint16 `pakparse:"value=0x1337"`
	Len     uint16
	Payload []byte `pakparse:"len=Len,maxlen=260"`
	Crc     uint16
}

In the above case, the Magic field is specified to contain a literal 0x1337, and the default big endian means the input bytes must be in order: {0x13, 0x37}. The parser will drop bytes until it finds that pattern. Len is just the next two bytes after it finds Magic. It will interpret Len as a uint16 and immediately return to searching for Magic if Len exceeds 260. Otherwise, the parser will read bytes into Payload until it has read Len bytes. Crc will just be the next two bytes. Then the parser will call a user defined check function, if present. If there isn't a check function or if the check function returns true, the parser writes the decoded struct to the output channel. Otherwise, it drops the packet and returns to searching for Magic.

Tag Specifics

If no pakparse tag is set, the parser will pull sizeof(field type) bytes from the stream.

If data is given, you inherently set a fixed length to len(provided data).

If len is given, it overrides default length behavior with the fixed length given. A length shorter than a default will pad the output with zeros. (e.g. reading 3 bytes into a uint32) A length larger than a default is undefined.

Mixing len and vlen is undefined.

Mixing len and maxlen is undefined.

Unexported struct fields are completely ignored, even if they have a pakparse tag.

Known Limitations

pakparse cannot handle bitpacked fields or optional fields.

Nested structs are not handled.

Example (VariablePacket)
/*
	Copyright 2019 Christopher Creager
	Copyright 2019 Ethan Reesor

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		    http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

// example_variablePacket_test.go: Complete example of parsing variable-length packets

package main

import (
	"bytes"
	"fmt"
	"log"
	"reflect"

	"gitlab.com/rigel314/pakparse"
)

type ExampleVariablePacket struct {
	Magic    uint16 `pakparse:"value=0x1337"`
	Len      uint16
	Payload  []byte `pakparse:"len=Len,maxlen=260"`
	Checksum uint16
}

func main() {
	c := new(pakparse.Config).Safe()

	// Add a validation function
	c.Check = func(x *ExampleVariablePacket) bool {
		// This function just returns true if Checksum is a hard coded value
		// A better validation would be to actually calculate the checksum and compare against the received Checksum
		return x.Checksum == 0x1234
	}

	// Assuming the protocol defines that Len includes the 2 Checksum bytes
	c.Count["Payload"] = func(x *ExampleVariablePacket) uint16 { return x.Len - 2 }

	p, err := pakparse.New(reflect.TypeOf(ExampleVariablePacket{}), c)
	if err != nil {
		log.Fatal(err)
	}

	// prepare some test data
	onesPl := [255]byte{}
	for i := 0; i < 255; i++ {
		onesPl[i] = 1
	}

	// send data into the parser
	s := new(pakparse.State)
	s.Consume(p, []byte{0x13, 0x37, 0x01, 0x01})
	s.Consume(p, onesPl[:])
	s.Consume(p, []byte{0x12, 0x34})

	x, ok := s.Next()
	assert(ok, "Expected a valid packet")

	v, ok := x.(ExampleVariablePacket)
	assert(ok, "Expected an ExampleVariablePacket")

	assert(v.Magic == 0x1337, "Expected Magic to equal 0x1337")
	assert(v.Len == 257, "Expected Len to equal 257")
	assert(bytes.Equal(v.Payload, onesPl[:]), "Expected Payload to equal [0, 1, ..., 254, 255]")
	assert(v.Checksum == 0x1234, "Expected checksum to equal 0x1234")

	fmt.Println("success")

}
Output:
success

Index

Examples

Constants

View Source
const MaxZeroByteReadCount = 100

MaxZeroByteReadCount holds the number of Read() attempts in a row that return (n=0, err=nil) before failing

Variables

View Source
var (
	ErrClosed        = io.EOF
	ErrReadZeroBytes = fmtErrorf("Read() returned 0 bytes %d times; bailing out", MaxZeroByteReadCount)
)

Custom errors that pakparse can return. Other errors from other packages might also be returned.

View Source
var ErrExpectedStructType = fmt.Errorf("expected a struct type")

ErrExpectedStructType is returned if New is called on a type other than a struct type

Functions

func Marshal added in v0.1.0

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

Marshal serializes `v` to bytes using `p`

func Unmarshal

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

Unmarshal parses DATA into V

Unmarshal creates a parser, initializes it, consumes the data, pops the parsed packet off the queue, and assigns the packet to V. If data is insufficient to parse as a packet, Unmarshal returns io.EOF.

See State.InitWithPointer, State.Consume, State.Next.

Types

type CheckFunction added in v0.1.0

type CheckFunction = func(packet reflect.Value, raw []byte) bool

A CheckFunction for a packet type checks whether a packet is valid

func VerifyCheckFunction added in v0.1.0

func VerifyCheckFunction(typ reflect.Type, fn interface{}) (CheckFunction, error)

VerifyCheckFunction verifies that FN is a valid packet check function for TYP and returns a reflection-based wrapper. See New.

A valid check function is one of:

  • func(*TYP) bool
  • func([]byte) bool
  • func(*TYP, []byte) bool
  • func([]byte, *TYP) bool

type Config

type Config struct {
	// Check is the check function. See VerifyCheckFunction.
	Check interface{}

	// Width is a map of field name => field width function. See VerifyLengthFunction.
	Width map[string]interface{}

	// Count is a map of field name => field count function. See VerifyLengthFunction.
	Count map[string]interface{}

	// Parser is a map of field name => field parser function. See VerifyParserFunction.
	Parser map[string]interface{}
}

Config allows for tuning and customization of packet parsing

func (*Config) Safe added in v0.1.0

func (c *Config) Safe() *Config

Safe ensures that collection properties of C are non-nil and returns C. If C is nil, Safe returns a new Config.

func (*Config) SetCheck added in v0.1.0

func (c *Config) SetCheck(fn interface{}) *Config

SetCheck sets the check function and returns C. See VerifyCheckFunction.

func (*Config) SetCount added in v0.1.0

func (c *Config) SetCount(name string, fn interface{}) *Config

SetCount sets the count function for a field and returns C. See VerifyLengthFunction.

func (*Config) SetParser added in v0.1.0

func (c *Config) SetParser(name string, fn interface{}) *Config

SetParser sets the parser function for a field and returns C. See VerifyParserFunction.

func (*Config) SetWidth added in v0.1.0

func (c *Config) SetWidth(name string, fn interface{}) *Config

SetWidth sets the width function for a field and returns C. See VerifyLengthFunction.

type Decoder

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

Decoder decodes packets from an io.Reader

func NewDecoder

func NewDecoder(parser *Parser, r io.Reader) *Decoder

NewDecoder creates a new decoder. The parser is built using reflection to look at the fields/tags of the struct type in typ.

The reader must be a ReadCloser or support deadlines, to prevent leaking goroutines.

func NewDecoderWithChannel

func NewDecoderWithChannel(parser *Parser, ch <-chan []byte) *Decoder

NewDecoderWithChannel creates a new decoder that reads from a <-chan []byte

SetPacketTimeout will succeed. Close will fail.

func (*Decoder) BytesConsumed

func (d *Decoder) BytesConsumed() int

BytesConsumed calls State.BytesConsumed

func (*Decoder) BytesDiscarded

func (d *Decoder) BytesDiscarded() int

BytesDiscarded calls State.BytesDiscarded

func (*Decoder) Close

func (d *Decoder) Close() error

Close terminates the parser's goroutines and cleans up

Example
r, w := iochan.Pipe(0)
defer w.Close()

p, err := pakparse.New(reflect.TypeOf(ExampleVariablePacket{}), nil)
if err != nil {
	log.Fatal(err)
}

d := pakparse.NewDecoder(p, r)
assert(d.SetReadTimeout(1*time.Millisecond) == nil, "Did not expect an error")

done := make(chan struct{})
go func() {
	<-time.After(time.Millisecond)
	assert(d.Close() == nil, "Did not expect an error")
	close(done)
}()

var v ExampleVariablePacket
err = d.Decode(&v)
assert(err == io.EOF, "Expected EOF")

<-done

fmt.Println(err)
Output:
EOF

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{}) error

Decode dequeues the oldest decoded packet. If no packets have been enqueued, Decode reads bytes from its data source until a packet has been decoded.

func (*Decoder) PacketsParsed

func (d *Decoder) PacketsParsed() int

PacketsParsed calls State.PacketsParsed

func (*Decoder) ResetStats

func (d *Decoder) ResetStats()

ResetStats calls State.ResetStats

func (*Decoder) SetPacketTimeout

func (d *Decoder) SetPacketTimeout(t time.Duration) error

SetPacketTimeout sets a maximum length of time to wait for a byte to be received. This allows a specified delay between bytes to drop the current working state and return to searching for the first struct field.

func (*Decoder) SetReadTimeout

func (d *Decoder) SetReadTimeout(t time.Duration) error

SetReadTimeout is used to set the (read) deadline of the underlying reader, if the reader supports setting deadlines.

This timeout can be used to ensure that the runloop used for reader-based implementations blocks for a maximum duration, ensuring that the decoder can be properly closed.

type FieldConfig added in v0.1.0

type FieldConfig struct {
	// Omit is used to omit fields from packet parsing.
	Omit bool

	// Order indicates the byte ordering to use when parsing a field.
	Order binary.ByteOrder

	// Parser is a custom function used to parse a field.
	Parser ParserFunction

	// Width is the byte-width of a field, or of members of a field for arrays.
	Width *LengthConfig

	// Count is the number of elements in an array field.
	Count *LengthConfig

	// MaxCount is the maximum element count for unbounded fields.
	MaxCount int

	// Value is the value of fixed-value fields.
	Value *big.Int
}

FieldConfig allows for tuning and customization of field parsing.

func ParseFieldConfig added in v0.1.0

func ParseFieldConfig(packetType reflect.Type, field reflect.StructField) (*FieldConfig, error)

ParseFieldConfig parses field parser configuration, given the packet type, field type, and field tag.

func (*FieldConfig) SetByteValue added in v0.1.0

func (c *FieldConfig) SetByteValue(v ...byte)

SetByteValue sets the field value to a byte sequence.

func (*FieldConfig) SetCount added in v0.1.0

func (c *FieldConfig) SetCount(v int)

SetCount sets the count of the field.

See VerifyLengthFunction.

func (*FieldConfig) SetCountFunc added in v0.1.0

func (c *FieldConfig) SetCountFunc(packetType reflect.Type, fn interface{}) error

SetCountFunc sets the count function to use for the field.

See VerifyLengthFunction.

func (*FieldConfig) SetIntValue added in v0.1.0

func (c *FieldConfig) SetIntValue(v int64)

SetIntValue sets the field value to an int.

func (*FieldConfig) SetParser added in v0.1.0

func (c *FieldConfig) SetParser(packetType reflect.Type, fn interface{}) error

SetParser sets the parser function to use for the field.

See VerifyParserFunction.

func (*FieldConfig) SetWidth added in v0.1.0

func (c *FieldConfig) SetWidth(v int)

SetWidth sets the width of the field.

See VerifyLengthFunction.

func (*FieldConfig) SetWidthFunc added in v0.1.0

func (c *FieldConfig) SetWidthFunc(packetType reflect.Type, fn interface{}) error

SetWidthFunc sets the width function to use for the field.

See VerifyLengthFunction.

type FieldParser added in v0.1.0

type FieldParser interface {
	// Name returns the name of the field
	Name() string

	// Size returns the size of the field
	//
	// Size() must return (n > 0, true) for a parser representing a fixed length
	// field. Size() must return (-1, false) for a parser representing a
	// variable-length field.
	Size() (n int, fixed bool)

	// Reset resets the state
	Reset(state interface{}, packet reflect.Value) (nstate interface{})

	// Consume consumes bytes and advances the parser
	Consume(data []byte, state interface{}, packet reflect.Value) (n int, nstate interface{}, status Status)

	// Produce produces bytes from the field value
	Produce(packet reflect.Value) ([]byte, error)
}

A FieldParser parses bytes into a field

Reset() and Consume() are called by State.Consume(). The parser state maintains a state value for each field parser. Each time field.Reset() or field.Consume() is called, the state value for that field is loaded, and the returned state value is stored.

func NewField added in v0.1.0

func NewField(typ reflect.Type, field reflect.StructField, config *FieldConfig) (FieldParser, error)

NewField creates a field parser.

NOTE, NewField expects `config` to be generated via ParseFieldConfig. It is much safer to call ParseFieldConfig and modify the result than to manually create `config`.

`config.Parser` will always override all other parsing.

func ParseField added in v0.1.0

func ParseField(typ reflect.Type, field reflect.StructField) (FieldParser, error)

ParseField calls ParseFieldConfig and NewField.

type LengthConfig added in v0.1.0

type LengthConfig struct {
	// Fixed indicates whether the width or count of the field is fixed
	Fixed bool

	// Value is the fixed width or count of a field
	Value int

	// Func calculates the width or count of a field
	Func LengthFunction
}

LengthConfig is used to specify the width or count of a field.

func (*LengthConfig) Calculate added in v0.1.0

func (c *LengthConfig) Calculate(packet reflect.Value) int

Calculate returns the calculated length of a field, given the current packet.

If Fixed is true, Calculate returns Value. If `c` is nil, Calculate returns -1. If Fixed is false and Func is nil, Calculate returns -1. If `packet` is invalid, Calculate returns -1. Otherwise, Calculate calls Func and returns the result.

func (*LengthConfig) CanCalculate added in v0.1.0

func (c *LengthConfig) CanCalculate() bool

CanCalculate returns whether the length can be calculated

func (*LengthConfig) IsFixed added in v0.1.0

func (c *LengthConfig) IsFixed() bool

IsFixed returns `c.Fixed`, or false if `c` is nil.

type LengthFunction added in v0.1.0

type LengthFunction = func(packet reflect.Value) int

A LengthFunction for a field calculates the length of a field from a partial packet

func VerifyLengthFunction added in v0.1.0

func VerifyLengthFunction(typ reflect.Type, fn interface{}) (LengthFunction, error)

VerifyLengthFunction verifies that FN is a valid field length function for TYP and returns a reflection-based wrapper. See New.

A valid length function is:

  • func(*TYP) INT_TYPE

INT_TYPE can be any built-in integer type.

type Marshaller added in v0.1.0

type Marshaller func(reflect.Value) []byte

A Marshaller converts a (specific type of) value to bytes

func NewValueMarshaller added in v0.1.0

func NewValueMarshaller(typ reflect.Type, order binary.ByteOrder, width int) Marshaller

NewValueMarshaller returns a marshaller for `typ` using byte ordering `order`. If `typ` is not a supported type, NewValueMarshaller will panic.

NewValueMarshaller does not currently support strings or pointers.

NewValueMarshaller does not and will not support channels, functions, interfaces, maps, uintptr, or unsafe pointers.

NewValueMarshaller does not support integers with platform-specific sizes, e.g. `int` and `uint`.

NewValueMarshaller supports booleans, numeric types (excepting `int` and `uint`), slices and arrays of supported types, and named types where the underlying type is supported (e.g. `type Custom uint16`).

If specified, `width` overrides the width of array and slice elements. `width` is ignored for other types. NewValueMarshaller will panic if `width` is greater than sizeof(typ.Elem()).

NewValueMarshaller has a fast path for `[]byte`; the resulting marshaller simply calls `value.Bytes()`. NewValueMarshaller has a fast path for `[...]byte`; the resulting marshaller creates a new slice with sufficient capacity and copies the array to the new slice. `byte` and `uint8` are interchangable. These fast paths will work for named types with an underlying type of `[]byte`. They will not work for slices and arrays with an element type that is not `byte`, regardless of the size of the element type, even if the element type is `type Custom byte`. This limitation is imposed by Go's type system, not by this package.

type Parser

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

A Parser captures the information necessary to parse packets

Each parser is tied to a specific packet type

func New added in v0.1.0

func New(typ reflect.Type, config *Config) (*Parser, error)

New creates a new parser for TYP using CONFIG. Unexported fields are skipped.

If a check function is specified, it is passed to VerifyCheckFunction. If successful, the (wrapped) check function is called each time a complete packet is decoded. If the check function returns false, the packet is discarded.

For each variable-length field, if a length function is specified, it is passed to VerifyLengthFunction. If successful, the (wrapped) length function is called immediately before the field is parsed. The partially parsed packet is passed to the length function. Specifying a length function for a fixed-length field is undefined. Specifying a length function will override the `vlen` tag.

For each field, if a parser function is specified, it is passed to VerifyParserFunction. If successful, the (wrapped) parser function is used to parse the field, overriding the default behavior.

Indeterminate-length fields (variable-length fields with no length function and no `len` or `vlen` tag) must be followed by a fixed-value field. The fixed-value field is used as a stop sequence for the indeterminate-length field. Fixed-length fields between the indeterminate-length field and the fixed-value field are allowed. Variable-length fields in-between are not. After creating a FieldParser for each field, New verifies these constraints, and updates the indeterminate-length fields with their stop sequences.

func (*Parser) AsFieldMarshaller added in v0.1.0

func (p *Parser) AsFieldMarshaller(field reflect.StructField) Marshaller

AsFieldMarshaller returns a Marshaller that will marshal a given field using `p`.

func (*Parser) AsFieldParser added in v0.1.0

func (p *Parser) AsFieldParser(field reflect.StructField) ParserFunction

AsFieldParser returns a ParserFunction that will parse a given field using `p`.

func (*Parser) Field added in v0.1.0

func (p *Parser) Field(i int) FieldParser

Field returns the Ith field of the parser

func (*Parser) NumField added in v0.1.0

func (p *Parser) NumField() int

NumField returns the number of fields

func (*Parser) Type added in v0.1.0

func (p *Parser) Type() reflect.Type

Type returns the packet type that this parser can parse

type ParserFunction added in v0.1.0

type ParserFunction = func(reset bool, data []byte, state reflect.Value, packet reflect.Value) (int, reflect.Value, Status)

A ParserFunction implements custom parsing for a field of a packet

func VerifyParserFunction added in v0.1.0

func VerifyParserFunction(typ reflect.Type, fn interface{}) (ParserFunction, error)

VerifyParserFunction verifies that FN is a valid field parser function for TYP and returns a reflection-based wrapper. See New.

A valid parser function is:

  • func(bool, []byte, STATE, TYP) (int, STATE, Status)

The first and second parameters, RESET and DATA, are mutually exclusive, when used by the parser. If RESET is true, DATA is nil.

The types of the third parameter and second return value, STATE_IN and STATE_OUT, are not required to be identical, so long as STATE_OUT can be passed as STATE_IN in a subsequent call.

The first return value, N, is the number of bytes consumed. This can be positive, negative, or zero. If it is negative, this indicates that values should be pulled off the internal buffer of processed data and reprocessed.

The last return value, STATUS, is used to indicate whether field parsing is complete, incomplete, or invalid.

Repeatedly returning N == 0 and STATUS == incomplete will stall the parser. The parser has checks that will cause a panic if this happens many times.

type State

type State struct {

	// Receive can be used to disable the packet queue and receive packets
	// directly
	Receive func(reflect.Value)

	// Discard can be used to capture discarded bytes
	Discard func([]byte)

	// Reject can be used to capture rejected packets
	Reject func(reflect.Value)
	// contains filtered or unexported fields
}

State represents a particular

func (*State) BytesConsumed

func (s *State) BytesConsumed() int

BytesConsumed returns the number of bytes that have been observed

func (*State) BytesDiscarded

func (s *State) BytesDiscarded() int

BytesDiscarded returns the number of bytes dropped between packets

func (*State) Consume

func (s *State) Consume(p *Parser, data []byte)

Consume calls StepPacket until no data remains.

func (*State) Encode

func (s *State) Encode(p *Parser, w io.Writer, v interface{}) error

Encode will serialize v to bytes then write to w as one write. Encode will be the inverse of the parser used by Decode. v must be the same type as the type the State was created with. Any fixed data fields will always use the fixed data value in the struct tag, regardless of the actual field value in v.

func (*State) Next

func (s *State) Next() (interface{}, bool)

Next pops a packet off the queue and returns it.

func (*State) PacketsDiscarded

func (s *State) PacketsDiscarded() int

PacketsDiscarded returns the number of times a partial packet was discarded

func (*State) PacketsParsed

func (s *State) PacketsParsed() int

PacketsParsed returns the number of full packets parsed successfully

func (*State) PacketsRejected added in v0.1.0

func (s *State) PacketsRejected() int

PacketsRejected returns the number of times a complete packet was rejected

func (*State) Produce added in v0.1.0

func (s *State) Produce(p *Parser, v reflect.Value) ([]byte, error)

Produce serializes `v` to bytes using `p`.

func (*State) Reset

func (s *State) Reset(p *Parser)

Reset discards the current parsed packet state

func (*State) ResetStats

func (s *State) ResetStats()

ResetStats sets the various informational counters to zero

func (*State) Step added in v0.1.0

func (s *State) Step(p *Parser, data []byte) (n int, unread []byte, status Status)

Step executes a parser step, processing the current field, returning the number of bytes read, any bytes that should be reprocessed, and the parsing status.

If `n` is positive or zero, `unread` is nil. Otherwise, `n` is `-len(unread)`.

If the current field parser returns a status of `Complete`, Step will increment the field counter. If the current field parser returns `Invalid`, the parser state will be reset, discarding the current packet. If a field parser returns `Incomplete`, Step will return.

func (*State) StepPacket added in v0.1.0

func (s *State) StepPacket(p *Parser, data []byte) (n int, unread []byte, status Status)

StepPacket calls Step until no more data is available or until a complete packet is parsed, returning the number of bytes read, any bytes that should be reprocessed, and the parsing status.

If `n` is positive or zero, `unread` is nil. Otherwise, `n` is `-len(unread)`.

StepPacket returns `Complete` when a complete packet has been parsed or `Incomplete` when more data is required. (When is `Invalid` returned?).

type Status

type Status int

Status represents the status of parsing a packet

const (
	// Invalid indicates that invalid data were received and the current parsing state should be discarded
	Invalid Status = iota
	// Incomplete indicates that the current field being parsed is incomplete and needs more data
	Incomplete
	// Complete indicates that the current field being parsed is complete and does not need more data
	Complete
)

func (Status) String added in v0.1.0

func (s Status) String() string

String returns the name of `s`, or "Status:#"

type Unmarshaller added in v0.1.0

type Unmarshaller func([]byte, reflect.Value)

An Unmarshaller converts bytes to a (specific type of) value

func NewValueUnmarshaller added in v0.1.0

func NewValueUnmarshaller(typ reflect.Type, order binary.ByteOrder, width int) Unmarshaller

NewValueUnmarshaller returns an unmarshaller for `typ` using byte ordering `order`. If `typ` is not a supported type, NewValueUnmarshaller will panic.

NewValueUnmarshaller does not currently support strings or pointers.

NewValueUnmarshaller does not and will not support channels, functions, interfaces, maps, uintptr, or unsafe pointers.

NewValueUnmarshaller does not support integers with platform-specific sizes, e.g. `int` and `uint`.

NewValueUnmarshaller supports booleans, numeric types (excepting `int` and `uint`), slices and arrays of supported types, and named types where the underlying type is supported (e.g. `type Custom uint16`).

If specified, `width` overrides the width of array and slice elements. `width` is ignored for other types. NewValueUnmarshaller will panic if `width` is greater than sizeof(typ.Elem()).

NewValueUnmarshaller has a fast path for `[]byte`; the resulting marshaller simply calls `value.Bytes()`. NewValueUnmarshaller has a fast path for `[...]byte`; the resulting marshaller creates a new slice with sufficient capacity and copies the array to the new slice. `byte` and `uint8` are interchangable. These fast paths will work for named types with an underlying type of `[]byte`. They will not work for slices and arrays with an element type that is not `byte`, regardless of the size of the element type, even if the element type is `type Custom byte`. This limitation is imposed by Go's type system, not by this package.

Jump to

Keyboard shortcuts

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