Packer is a simple, efficient, and lightweight Go library for binary serialization. It provides a straightforward API to encode various Go data types into a byte stream and decode them back, making it ideal for network protocols, file storage, or any application requiring compact data representation.
The library is built for performance and ease of use, offering both struct-based encoder/decoder workflows and standalone functions for granular control.
- Wide Type Support: Natively handles
bool,(u)int8-64,float32/64,string,[]byte, and*bytes.Buffer. - Consistent Endianness: All multi-byte numeric types are encoded and decoded using Big Endian byte order for cross-platform compatibility.
- Extensible: Easily support custom data structures by implementing the
EncodeableandDecodableinterfaces. - Performance-Oriented: Includes optimizations like a zero-copy
[]bytetostringconversion usingunsafe. - Simple Streaming API: The
BinaryEncoderandBinaryDecoderstructs operate on a continuous stream of bytes, making it easy to serialize and deserialize complex sequences of data.
go get github.com/FrogoAI/packer
The core of the library is the BinaryEncoder for writing data and the BinaryDecoder for reading it. You can encode multiple values sequentially and then decode them in the same order.
Here is a basic example:
package main
import (
"fmt"
"github.com/FrogoAI/packer"
)
func main() {
// 1. Create a new encoder
encoder := packer.NewBinaryEncoder()
// 2. Encode a sequence of different data types
_ = encoder.Encode(uint32(123456))
_ = encoder.Encode("Hello, Packer!")
_ = encoder.Encode(float64(3.14159))
_ = encoder.Encode(true)
_ = encoder.Encode([]byte{0xDE, 0xAD, 0xBE, 0xEF})
// 3. Get the resulting byte slice
encodedData := encoder.Bytes()
fmt.Printf("Encoded Data: %x\n", encodedData)
// 4. Create a decoder with the encoded data
decoder := packer.NewBinaryDecoder(encodedData)
// 5. Decode the values back into variables in the same order
var myUint32 uint32
var myString string
var myFloat64 float64
var myBool bool
var myBytes []byte
_ = decoder.Decode(&myUint32)
_ = decoder.Decode(&myString)
_ = decoder.Decode(&myFloat64)
_ = decoder.Decode(&myBool)
_ = decoder.Decode(&myBytes)
// 6. Verify the results
fmt.Printf("Decoded uint32: %d\n", myUint32)
fmt.Printf("Decoded string: %s\n", myString)
fmt.Printf("Decoded float64: %f\n", myFloat64)
fmt.Printf("Decoded bool: %t\n", myBool)
fmt.Printf("Decoded bytes: %x\n", myBytes)
}
Encoded Data: 0001e2400000000e48656c6c6f2c205061636b657221400921f9f01b866e0100000004deadbeef
Decoded uint32: 123456
Decoded string: Hello, Packer!
Decoded float64: 3.141590
Decoded bool: true
Decoded bytes: deadbeef
Benchmarks from binary_test.go show the performance characteristics of the library. The standalone functions (DecodeString, EncodeString) offer slightly different performance profiles due to reduced overhead compared to the struct-based methods.
| Benchmark Operation | Nanoseconds per Operation (ns/op) |
|---|---|
BenchmarkBinaryEncoder (struct) |
69.00 ns/op |
BenchmarkEncode (standalone) |
71.73 ns/op |
BenchmarkBinaryDecoder (struct) |
37.94 ns/op |
BenchmarkDecode (standalone) |
22.54 ns/op |
This project is licensed under the MIT License. See the LICENSE file for details.