- Notifications
You must be signed in to change notification settings - Fork0
Better binary packing for Go
License
v2fly/struc
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Struc exists to pack and unpack C-style structures from bytes, which is useful for binary files and network protocols. It could be considered an alternative toencoding/binary
, which requires massive boilerplate for some similar operations.
Take a look at anexample comparingstruc
andencoding/binary
Struc considers usability first. That said, it does cache reflection data and aims to be competitive withencoding/binary
struct packing in every way, including performance.
typeExamplestruct {Varint`struc:"int32,sizeof=Str"`StrstringWeird []byte`struc:"[8]int64"`Var []int`struc:"[]int32,little"`}
Var []int `struc:"[]int32,little,sizeof=StringField"`
will pack Var as a slice of little-endian int32, and link it as the size ofStringField
.sizeof=
: Indicates this field is a number used to track the length of a another field.sizeof
fields are automatically updated onPack()
based on the current length of the tracked field, and are used to size the target field duringUnpack()
.- Bare values will be parsed as type and endianness.
big
(default)little
pad
- this type ignores field contents and is backed by a[length]byte
containing nullsbool
byte
int8
,uint8
int16
,uint16
int32
,uint32
int64
,uint64
float32
float64
Types can be indicated as arrays/slices using[]
syntax. Example:[]int64
,[8]int32
.
Bare slice types (those with no[size]
) must have a linkedSizeof
field.
Private fields are ignored when packing and unpacking.
package mainimport ("bytes""github.com/lunixbochs/struc")typeExamplestruct {Aint`struc:"big"`// B will be encoded/decoded as a 16-bit int (a "short")// but is stored as a native int in the structBint`struc:"int16"`// the sizeof key links a buffer's size to any int fieldSizeint`struc:"int8,little,sizeof=Str"`Strstring// you can get freaky if you wantStr2string`struc:"[5]int64"`}funcmain() {varbuf bytes.Buffert:=&Example{1,2,0,"test","test2"}err:=struc.Pack(&buf,t)o:=&Example{}err=struc.Unpack(&buf,o)}
BenchmarkEncode
uses struc.Stdlib
benchmarks use equivalentencoding/binary
code.Manual
encodes without any reflection, and should be considered an upper bound on performance (which generated code based on struc definitions should be able to achieve).
BenchmarkEncode 1000000 1265 ns/opBenchmarkStdlibEncode 1000000 1855 ns/opBenchmarkManualEncode 5000000 284 ns/opBenchmarkDecode 1000000 1259 ns/opBenchmarkStdlibDecode 1000000 1656 ns/opBenchmarkManualDecode 20000000 89.0 ns/op