binary

package module
v0.0.0-...-29b974f Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2017 License: MIT Imports: 7 Imported by: 0

README

binary

Version Build status Coverage Status Go Report Card GoDoc License


Package binary is uesed to Encode/Decode between go data and byte slice.

The main purpose of this package is to replace package "std.binary".

Compare with other serialization package, this package is with full-feature as gob and protocol buffers, and with high-performance and lightweight as std.binary.

It is designed as a common solution to easily encode/decode between go data and byte slice.

It is recommended to use in net protocol serialization and go memory data serialization such as DB.


Install

$ go get -u github.com/vipally/binary
import(
	"github.com/vipally/binary"
)

Change log:

v1.2.0

1.use field tag `binary:"packed"` to encode ints value as varint/uvarint 
  for reged structs.
2.add method Encoder.ResizeBuffer.

v1.1.0

1.fix issue#1 nil pointer encode/decode error.
2.pack 8 bool values as bits in one byte.
3.put one bool bit for pointer fields to check if it is a nil pointer.
4.rename Pack/Unpack to Encode/Decode.

v1.0.0

1.full-type support like gob.
2.light-weight as std.binary.
3.high-performance as std.binary and gob.
4.encoding with fower bytes than std.binary and gob.
5.use RegStruct to improve performance of struct encoding/decoding.
6.take both advantages of std.binary and gob.
7.recommended using in net protocol serialization and DB serialization.

Todo:

1.[Encoder/Decoder].RegStruct to speed up local Coder.
2.[Encoder/Decoder].RegSerializer to speed up BinarySerializer search.
3.reg interface to using BinarySerializer interface.

CopyRight 2017 @Ally Dale. All rights reserved.

Author : Ally Dale(vipally@gmail.com)

Blog : http://blog.csdn.net/vipally

Site : https://github.com/vipally


1. Support all serialize-able basic types:

int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64,
float32, float64, complex64, complex128,
bool, string, slice, array, map, struct.
And their direct pointers. 
eg: *string, *struct, *map, *slice, *int32.

Use RegStruct to improve struct encoding/decoding efficiency.

type someRegedStruct struct {
	A int `binary:"ignore"`
	B string
	C uint
}
binary.RegStruct((*someRegedStruct)(nil))

If data implements interface BinaryEncoder, it will use data.Encode/data.Decode 
to encode/decode data.
NOTE that data.Decode must implement on pointer receiever to enable modifying
receiever.Even though Size/Encode of data can implement on non-pointer receiever,
binary.Encode(&data, nil) is required if data has implement interface BinaryEncoder.
binary.Encode(data, nil) will probably NEVER use BinaryEncoder methods to Encode/Decode
data.
eg:

import "github.com/vipally/binary"

//1.Encode with default buffer
if bytes, err := binary.Encode(&data, nil); err==nil{
	//...
}

//2.Encode with existing buffer
size := binary.Sizeof(data)
buffer := make([]byte, size)
if bytes, err := binary.Encode(&data, buffer); err==nil{
	//...
}

//3.Decode from buffer
if err := binary.Decode(bytes, &data); err==nil{
	//...
}

3. [advanced usage] Encoder/Decoder are exported types aviable for encoding/decoding.

eg:
encoder := binary.NewEncoder(bufferSize)
encoder.Uint32(u32)
encoder.String(str)
encodeResult := encoder.Buffer()

decoder := binary.NewDecoder(buffer)
u32 := decoder.Uint32()
str := decoder.String()

4. Put an extra length field(uvarint,1~10 bytes) before string, slice, array, map.

eg: 
var s string = "hello"
will be encoded as:
[]byte{0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}

5. Pack bool array with bits.

eg: 
[]bool{true, true, true, false, true, true, false, false, true}
will be encoded as:
[]byte{0x9, 0x37, 0x1}

6. Hide struct field when encoding/decoding.

Only encode/decode exported fields.
Support using field tag `binary:"ignore"` to disable encode/decode fields.
eg: 
type S struct{
    A uint32
	b uint32
	_ uint32
	C uint32 `binary:"ignore"`
}
Only field "A" will be encode/decode.

7. Auto allocate for slice, map and pointer.

eg: 
type S struct{
    A *uint32
	B *string
	C *[]uint8
	D []uint32
}
It will new pointers for fields "A, B, C",
and make new slice for fields "*C, D" when decode.

8. int/uint values will be encoded as varint/uvarint(1~10 bytes).

eg: 
uint(1)     will be encoded as: []byte{0x1}
uint(128)   will be encoded as: []byte{0x80, 0x1}
uint(32765) will be encoded as: []byte{0xfd, 0xff, 0x1}
int(-5)     will be encoded as: []byte{0x9}
int(-65)    will be encoded as: []byte{0x81, 0x1}

9. Test results.

Enncoding size(see example of Sizeof).

Encoding bytes is much shorter than std.binary and gob.

var s struct {
	Int8        int8
	Int16       int16
	Int32       int32
	Int64       int64
	Uint8       uint8
	Uint16      uint16
	Uint32      uint32
	Uint64      uint64
	Float32     float32
	Float64     float64
	Complex64   complex64
	Complex128  complex128
	Array       [10]uint8
	Bool        bool
	BoolArray   [100]bool
	Uint32Array [10]uint32
}

Output:
Sizeof(s)  = 133
std.Size(s)= 217
gob.Size(s)= 412

Benchmark test result.

Pack/Unpack unregisted struct is a little slower(80%) than std.binary.Read/std.binary.Write
Pack/Unpack registed struct is much faster(200%) than std.binary.Read/std.binary.Write
Pack/Unpack int array is much faster(230%) than std.binary.Read/std.binary.Write
Pack/Unpack string is a little faster(140%) than gob.Encode/gob.Decode

BenchmarkGobEncodeStruct     	 1000000	      1172 ns/op	 300.32 MB/s
BenchmarkStdWriteStruct      	 1000000	      3154 ns/op	  23.78 MB/s
BenchmarkWriteStruct         	  500000	      3954 ns/op	  18.71 MB/s
BenchmarkWriteRegedStruct    	 1000000	      1627 ns/op	  45.48 MB/s
BenchmarkPackStruct          	  500000	      3642 ns/op	  20.32 MB/s
BenchmarkPackRegedStruct     	 1000000	      1542 ns/op	  47.99 MB/s
BenchmarkGobDecodeStruct     	 3000000	       651 ns/op	 540.40 MB/s
BenchmarkStdReadStruct       	 1000000	      2008 ns/op	  37.35 MB/s
BenchmarkReadStruct          	  500000	      2386 ns/op	  31.01 MB/s
BenchmarkReadRegedStruct     	 1000000	      1194 ns/op	  61.97 MB/s
BenchmarkUnackStruct         	 1000000	      2293 ns/op	  32.27 MB/s
BenchmarkUnpackRegedStruct   	 2000000	       935 ns/op	  79.14 MB/s
BenchmarkGobEncodeInt1000    	  100000	     22871 ns/op	 219.58 MB/s
BenchmarkStdWriteInt1000     	   30000	     49502 ns/op	  80.80 MB/s
BenchmarkWriteInt1000        	   50000	     26001 ns/op	 153.91 MB/s
BenchmarkPackInt1000         	  100000	     21601 ns/op	 185.27 MB/s
BenchmarkStdReadInt1000      	   30000	     44035 ns/op	  90.84 MB/s
BenchmarkReadInt1000         	   50000	     29761 ns/op	 134.47 MB/s
BenchmarkUnackInt1000        	   50000	     25001 ns/op	 160.07 MB/s
BenchmarkGobEncodeString     	 3000000	       444 ns/op	 301.56 MB/s
BenchmarkStdWriteString 		unsupported 
BenchmarkWriteString         	 3000000	       455 ns/op	 285.49 MB/s
BenchmarkPackString          	 5000000	       337 ns/op	 385.05 MB/s
BenchmarkGobDecodeString     	 1000000	      1266 ns/op	 105.84 MB/s
BenchmarkStdReadString 			unsupported 
BenchmarkReadString          	 3000000	       550 ns/op	 236.06 MB/s
BenchmarkUnackString         	 5000000	       298 ns/op	 435.92 MB/s

With full-datatype support like gob.

Followed struct fullStruct is an aviable type that contains all supported types.
Which is not valid for std.binary.

type fullStruct struct {
	Int8       int8
	Int16      int16
	Int32      int32
	Int64      int64
	Uint8      uint8
	Uint16     uint16
	Uint32     uint32
	Uint64     uint64
	Float32    float32
	Float64    float64
	Complex64  complex64
	Complex128 complex128
	Array      [4]uint8
	Bool       bool
	BoolArray  [9]bool

	LittleStruct  littleStruct
	PLittleStruct *littleStruct
	String        string
	PString       *string
	PInt32        *int32
	Slice         []*littleStruct
	PSlice        *[]*string
	Float64Slice  []float64
	BoolSlice     []bool
	Uint32Slice   []uint32
	Map           map[string]*littleStruct
	Map2          map[string]uint16
	IntSlice      []int
	UintSlice     []uint
}

Do not supported types.

Followed struct TDoNotSupport is an invalid type that every field is invalid.

type TDoNotSupport struct {
	DeepPointer   **uint32
	Uintptr       uintptr
	UnsafePointer unsafe.Pointer
	Ch            chan bool
	Map           map[uintptr]uintptr
	Map2          map[int]uintptr
	Map3          map[uintptr]int
	Slice         []uintptr
	Array         [2]uintptr
	Array2        [2][2]uintptr
	Array3        [2]struct{ A uintptr }
	Func          func()
	Struct        struct {
		PStruct *struct {
			PPUintptr **uintptr
		}
	}
}

License.

Under MIT license.

Copyright (c) 2017 Ally Dale<vipally@gmail.com>
Author  : Ally Dale<vipally@gmail.com>
Site    : https://github.com/vipally
Origin  : https://github.com/vipally/binary

Documentation

Overview

Package binary is uesed to Encode/Decode between go data and byte slice.

The main purpose of this package is to replace package "std.binary". The design goal is to take both advantages of std.binary(encoding/binary) and gob.

Upgraded from std.binary(encoding/binary).

Compare with other serialization package, this package is with full-feature as gob and protocol buffers, and with high-performance and lightweight as std.binary. It is designed as a common solution to easily encode/decode between go data and byte slice. It is recommended to use in net protocol serialization and go memory data serialization such as DB.

Support all serialize-able data types:

int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64,
float32, float64, complex64, complex128,
bool, string, slice, array, map, struct.
int/uint will be encoded as varint(1~10 bytes).
And their direct pointers.
eg: *string, *struct, *map, *slice, *int32.

Here is the main feature of this package.

  1. as light-weight as std.binary
  2. with full-type support like gob.
  3. as high-performance as std.binary and gob.
  4. encoding with fewer bytes than std.binary and gob.
  5. use RegStruct to improve performance of struct encoding/decoding
  6. recommended using in net protocol serialization and DB serialization

Under MIT license.

Copyright (c) 2017 Ally Dale<vipally@gmail.com>
Author  : Ally Dale<vipally@gmail.com>
Site    : https://github.com/vipally
Origin  : https://github.com/vipally/binary

Index

Examples

Constants

View Source
const (
	MaxVarintLen16 = 3
	MaxVarintLen32 = 5
	MaxVarintLen64 = 10
)

MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.

Variables

View Source
var (
	// LittleEndian is the little-endian implementation of Endian.
	LittleEndian littleEndian
	// BigEndian is the big-endian implementation of Endian.
	BigEndian bigEndian
	//DefaultEndian is LittleEndian
	DefaultEndian = LittleEndian
)
View Source
var (
	// ErrNotEnoughSpace buffer not enough
	ErrNotEnoughSpace = errors.New("not enough space")
)

Functions

func Decode

func Decode(buffer []byte, data interface{}) error

Decode unmarshal go data from byte array. data must be interface of pointer for modify. It will make new pointer or slice/map for nil-field of data.

Example
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	var s struct {
		A uint32
		B int
		C string
	}
	buffer := []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}

	err := binary.Decode(buffer, &s)
	if err != nil {
		fmt.Println("binary.Decode failed:", err)
	}
	fmt.Printf("%+v", s)

}
Output:

{A:287454020 B:-5 C:hello}

func Encode

func Encode(data interface{}, buffer []byte) ([]byte, error)

Encode marshal go data to byte array. nil buffer is aviable, it will create new buffer if necessary.

Example
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	var data struct {
		A uint32
		B int
		C string
	}
	data.A = 0x11223344
	data.B = -5
	data.C = "hello"

	b, err := binary.Encode(data, nil)
	if err != nil {
		fmt.Println("binary.Encode failed:", err)
	}
	fmt.Printf("Encode:\n%+v\n%#v", data, b)

}
Output:

Encode:
{A:287454020 B:-5 C:hello}
[]byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}
Example (BoolArray)
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	var data = []bool{true, true, true, false, true, true, false, false, true}
	b, err := binary.Encode(data, nil)
	if err != nil {
		fmt.Println(err)
	}

	if size := binary.Sizeof(data); size != len(b) {
		fmt.Printf("Encode bool array:\ngot %#v %+v\nneed %+v\n", len(b), b, size)
	}
	fmt.Printf("Encode bool array:\n%#v\nsize=%d result=%#v", data, len(b), b)

}
Output:

Encode bool array:
[]bool{true, true, true, false, true, true, false, false, true}
size=3 result=[]byte{0x9, 0x37, 0x1}
Example (Bools)
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	type boolset struct {
		A uint8   //0xa
		B bool    //true
		C uint8   //0xc
		D []bool  //[]bool{true, false, true}
		E bool    //true
		F *uint32 //false
		G bool    //true
		H uint8   //0x8
	}
	var data = boolset{
		0xa, true, 0xc, []bool{true, false, true}, true, nil, true, 0x8,
	}
	b, err := binary.Encode(data, nil)
	if err != nil {
		fmt.Println(err)
	}

	if size := binary.Sizeof(data); size != len(b) {
		fmt.Printf("Encode got %#v %+v\nneed %+v\n", len(b), b, size)
	}
	fmt.Printf("Encode bools:\n%+v\nsize=%d result=%#v", data, len(b), b)

}
Output:

Encode bools:
{A:10 B:true C:12 D:[true false true] E:true F:<nil> G:true H:8}
size=6 result=[]byte{0xa, 0xb, 0xc, 0x3, 0x5, 0x8}
Example (PackedInts)
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	type regedPackedInts struct {
		A int16    `binary:"packed"`
		B int32    `binary:"packed"`
		C int64    `binary:"packed"`
		D uint16   `binary:"packed"`
		E uint32   `binary:"packed"`
		F uint64   `binary:"packed"`
		G []uint64 `binary:"packed"`
		H uint     `binary:"ignore"`
	}
	binary.RegStruct((*regedPackedInts)(nil))

	var data = regedPackedInts{1, 2, 3, 4, 5, 6, []uint64{7, 8, 9}, 10}
	b, err := binary.Encode(data, nil)
	if err != nil {
		fmt.Println(err)
	}

	if size := binary.Sizeof(data); size != len(b) {
		fmt.Printf("PackedInts got %+v %+v\nneed %+v\n", len(b), b, size)
	}

	fmt.Printf("Encode packed ints:\n%+v\nsize=%d result=%#v", data, len(b), b)

}
Output:

Encode packed ints:
{A:1 B:2 C:3 D:4 E:5 F:6 G:[7 8 9] H:10}
size=10 result=[]byte{0x2, 0x4, 0x6, 0x4, 0x5, 0x6, 0x3, 0x7, 0x8, 0x9}
Example (Withbuffer)
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	var data struct {
		A uint32
		B int
		C string
	}
	data.A = 0x11223344
	data.B = -5
	data.C = "hello"
	size := binary.Sizeof(data)
	buffer := make([]byte, size)

	b, err := binary.Encode(data, buffer)
	if err != nil {
		fmt.Println("binary.Encode failed:", err)
	}
	fmt.Printf("Encode:\n%+v\n%#v", data, b)

}
Output:

Encode:
{A:287454020 B:-5 C:hello}
[]byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}

func MakeEncodeBuffer

func MakeEncodeBuffer(data interface{}, buffer []byte) ([]byte, error)

MakeEncodeBuffer create enough buffer to encode data. nil buffer is aviable, it will create new buffer if necessary.

func PutUvarint

func PutUvarint(buf []byte, x uint64) int

PutUvarint encodes a uint64 into buf and returns the number of bytes written. If the buffer is too small, PutUvarint will panic.

func PutVarint

func PutVarint(buf []byte, x int64) int

PutVarint encodes an int64 into buf and returns the number of bytes written. If the buffer is too small, PutVarint will panic.

func Read

func Read(r io.Reader, endian Endian, data interface{}) error

Read reads structured binary data from r into data. Data must be a pointer to a fixed-size value or a slice of fixed-size values. Bytes read from r are decoded using the specified byte order and written to successive fields of the data. When decoding boolean values, a zero byte is decoded as false, and any other non-zero byte is decoded as true. When reading into structs, the field data for fields with blank (_) field names is skipped; i.e., blank field names may be used for padding. When reading into a struct, all non-blank fields must be exported.

The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, Read returns ErrUnexpectedEOF.

Example
package main

import (
	"bytes"
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	var pi float64
	b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
	buf := bytes.NewReader(b)
	err := binary.Read(buf, binary.LittleEndian, &pi)
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Print(pi)

}
Output:

3.141592653589793

func ReadUvarint

func ReadUvarint(r io.ByteReader) (uint64, error)

ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.

func ReadVarint

func ReadVarint(r io.ByteReader) (int64, error)

ReadVarint reads an encoded signed integer from r and returns it as an int64.

func RegStruct

func RegStruct(data interface{}) error

RegStruct regist struct info to improve encoding/decoding efficiency. Regist by a nil pointer is aviable. RegStruct((*someStruct)(nil)) is recommended usage.

Example
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	type someRegedStruct struct {
		A int    `binary:"ignore"`
		B uint64 `binary:"packed"`
		C string
		D uint
	}
	binary.RegStruct((*someRegedStruct)(nil))

	var data = someRegedStruct{1, 2, "hello", 3}
	b, err := binary.Encode(data, nil)
	if err != nil {
		fmt.Println(err)
	}

	if size := binary.Sizeof(data); size != len(b) {
		fmt.Printf("RegedStruct got %+v %+v\nneed %+v\n", len(b), b, size)
	}

	fmt.Printf("Encode reged struct:\n%+v\nsize=%d result=%#v", data, len(b), b)

}
Output:

Encode reged struct:
{A:1 B:2 C:hello D:3}
size=8 result=[]byte{0x2, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x3}

func Size

func Size(data interface{}) int

Size is same to Sizeof. Size returns how many bytes Write would generate to encode the value v, which must be a serialize-able value or a slice/map of serialize-able values, or a pointer to such data. If v is neither of these, Size returns -1.

func Sizeof

func Sizeof(data interface{}) int

Sizeof returns how many bytes Write would generate to encode the value v, which must be a serialize-able value or a slice/map/struct of serialize-able values, or a pointer to such data. If v is neither of these, Size returns -1. If data implements interface BinarySizer, it will use data.Size first. It will panic if data implements interface BinarySizer or BinaryEncoder only.

Example
package main

import (
	"bytes"
	"encoding/gob"
	"fmt"

	std "encoding/binary"

	"github.com/vipally/binary"
)

func main() {
	var s struct {
		Int8        int8
		Int16       int16
		Int32       int32
		Int64       int64
		Uint8       uint8
		Uint16      uint16
		Uint32      uint32
		Uint64      uint64
		Float32     float32
		Float64     float64
		Complex64   complex64
		Complex128  complex128
		Array       [10]uint8
		Bool        bool
		BoolArray   [100]bool
		Uint32Array [10]uint32
	}

	buf := bytes.NewBuffer(make([]byte, 0, 1024))
	coder := gob.NewEncoder(buf)
	coder.Encode(s)
	gobSize := len(buf.Bytes())

	stdSize := std.Size(s)
	size := binary.Sizeof(s)

	fmt.Printf("Sizeof(s)  = %d\nstd Size(s)= %d\ngob Size(s)= %d", size, stdSize, gobSize)

}
Output:

Sizeof(s)  = 133
std Size(s)= 217
gob Size(s)= 412

func SizeofUvarint

func SizeofUvarint(ux uint64) int

SizeofUvarint return bytes number of an uint64 value store as uvarint

func SizeofVarint

func SizeofVarint(x int64) int

SizeofVarint return bytes number of an int64 value store as varint

func ToUvarint

func ToUvarint(x int64) uint64

ToUvarint convert an int64 value to uint64 ZigZag-encoding value for encoding. Different from uint64(x), it will move sign bit to bit 0. To help to cost fewer bytes for little negative numbers. eg: -5 will be encoded as 0x9.

func ToVarint

func ToVarint(ux uint64) int64

ToVarint decode an uint64 ZigZag-encoding value to original int64 value.

func Uvarint

func Uvarint(buf []byte) (uint64, int)

Uvarint decodes a uint64 from buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 meaning:

	n == 0: buf too small
	n  < 0: value larger than 64 bits (overflow)
             and -n is the number of bytes read

func Varint

func Varint(buf []byte) (int64, int)

Varint decodes an int64 from buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 with the following meaning:

	n == 0: buf too small
	n  < 0: value larger than 64 bits (overflow)
             and -n is the number of bytes read

func Write

func Write(w io.Writer, endian Endian, data interface{}) error

Write writes the binary representation of data into w. Data must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. Boolean values encode as one byte: 1 for true, and 0 for false. Bytes written to w are encoded using the specified byte order and read from successive fields of the data. When writing structs, zero values are written for fields with blank (_) field names.

Example
package main

import (
	"bytes"
	"fmt"
	"math"

	"github.com/vipally/binary"
)

func main() {
	buf := new(bytes.Buffer)
	var pi float64 = math.Pi
	err := binary.Write(buf, binary.LittleEndian, pi)
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	fmt.Printf("%#v", buf.Bytes())

}
Output:

[]byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x9, 0x40}
Example (Multi)
package main

import (
	"bytes"
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	buf := new(bytes.Buffer)
	var data = []interface{}{
		uint16(61374),
		int8(-54),
		uint8(254),
	}
	for _, v := range data {
		err := binary.Write(buf, binary.LittleEndian, v)
		if err != nil {
			fmt.Println("binary.Write failed:", err)
		}
	}
	fmt.Printf("%#v", buf.Bytes())

}
Output:

[]byte{0xbe, 0xef, 0xca, 0xfe}

Types

type BinaryDecoder

type BinaryDecoder interface {
	Decode(buffer []byte) error
}

BinaryDecoder is an interface to define go data Decode method.

type BinaryEncoder

type BinaryEncoder interface {
	Encode(buffer []byte) ([]byte, error)
}

BinaryEncoder is an interface to define go data Encode method. buffer is nil-able.

type BinarySerializer

type BinarySerializer interface {
	BinarySizer
	BinaryEncoder
	BinaryDecoder
}

BinarySerializer defines the go data Size/Encode/Decode method

Example
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

type S struct {
	A uint32
	B int
	C string
}

func (this *S) Size() int {
	size := binary.Sizeof(this.A) + binary.Sizeof(this.C) + binary.Sizeof(int16(this.B))
	return size
}
func (this *S) Encode(buffer []byte) ([]byte, error) {
	buff, err := binary.MakeEncodeBuffer(this, buffer)
	if err != nil {
		return nil, err
	}
	encoder := binary.NewEncoderBuffer(buff)
	encoder.Value(this.A)
	encoder.Int16(int16(this.B), false)
	encoder.Value(this.C)
	return encoder.Buffer(), nil
}
func (this *S) Decode(buffer []byte) error {
	decoder := binary.NewDecoder(buffer)
	decoder.Value(&this.A)
	this.B = int(decoder.Int16(false))
	decoder.Value(&this.C)
	return nil
}
func main() {
	/*
		type S struct {
			A uint32
			B int
			C string
		}
		func (this *S) Size() int {
			size := binary.Sizeof(this.A) + binary.Sizeof(this.C) + binary.Sizeof(int16(this.B))
			return size
		}
		func (this *S) Encode() ([]byte, error) {
			encoder := binary.NewEncoder(this.Size())
			encoder.Value(this.A)
			encoder.Int16(int16(this.B), false)
			encoder.Value(this.C)
			return encoder.Buffer(), nil
		}
		func (this *S) Decode(buffer []byte) error {
			decoder := binary.NewDecoder(buffer)
			decoder.Value(&this.A)
			this.B = int(decoder.Int16(false))
			decoder.Value(&this.C)
			return nil
		}
	*/
	var data, dataDecode S
	data.A = 0x11223344
	data.B = -5
	data.C = "hello"

	b, err := binary.Encode(&data, nil)
	if err != nil {
		fmt.Println("binary.Encode failed:", err)
	}

	err = binary.Decode(b, &dataDecode)
	if err != nil {
		fmt.Println("binary.Decode failed:", err)
	}
	fmt.Printf("%+v\n%#v\n%+v", data, b, dataDecode)

}
Output:

{A:287454020 B:-5 C:hello}
[]byte{0x44, 0x33, 0x22, 0x11, 0xfb, 0xff, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}
{A:287454020 B:-5 C:hello}

type BinarySizer

type BinarySizer interface {
	Size() int
}

BinarySizer is an interface to define go data Size method.

type BytesReader

type BytesReader []byte

BytesReader transform bytes as Reader

func (*BytesReader) Read

func (p *BytesReader) Read(data []byte) (n int, err error)

Read from bytes

type BytesWriter

type BytesWriter []byte

BytesWriter transform bytes as Writer

func (*BytesWriter) Write

func (p *BytesWriter) Write(data []byte) (n int, err error)

Write to bytes

type Decoder

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

Decoder is used to decode byte array to go data.

Example
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	buffer := []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}

	decoder := binary.NewDecoder(buffer)
	u32 := decoder.Uint32(false)
	i, _ := decoder.Varint()
	str := decoder.String()
	fmt.Printf("%#v %#v %#v", u32, i, str)

}
Output:

0x11223344 -5 "hello"

func NewDecoder

func NewDecoder(buffer []byte) *Decoder

NewDecoder make a new Decoder object with buffer.

func NewDecoderEndian

func NewDecoderEndian(buffer []byte, endian Endian) *Decoder

NewDecoderEndian make a new Decoder object with buffer and endian.

func (*Decoder) Bool

func (decoder *Decoder) Bool() bool

Bool decode a bool value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Buffer

func (cder *Decoder) Buffer() []byte

Buffer returns the byte slice that has been encoding/decoding.

func (*Decoder) Cap

func (cder *Decoder) Cap() int

Cap returns number total bytes of cder coder buffer.

func (*Decoder) Complex128

func (decoder *Decoder) Complex128() complex128

Complex128 decode a complex128 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Complex64

func (decoder *Decoder) Complex64() complex64

Complex64 decode a complex64 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Float32

func (decoder *Decoder) Float32() float32

Float32 decode a float32 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Float64

func (decoder *Decoder) Float64() float64

Float64 decode a float64 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Init

func (decoder *Decoder) Init(buffer []byte, endian Endian)

Init initialize Encoder with buffer and endian.

func (*Decoder) Int

func (decoder *Decoder) Int() int

Int decode an int value from Decoder buffer. It will panic if buffer is not enough. It use Varint() to decode as varint(1~10 bytes)

func (*Decoder) Int16

func (decoder *Decoder) Int16(packed bool) int16

Int16 decode an int16 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Int32

func (decoder *Decoder) Int32(packed bool) int32

Int32 decode an int32 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Int64

func (decoder *Decoder) Int64(packed bool) int64

Int64 decode an int64 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Int8

func (decoder *Decoder) Int8() int8

Int8 decode an int8 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Len

func (cder *Decoder) Len() int

Len returns unmber of bytes that has been encoding/decoding.

func (*Decoder) Reset

func (cder *Decoder) Reset()

Reset move the read/write pointer to the beginning of buffer and set all reseted bytes to 0.

func (*Decoder) Skip

func (decoder *Decoder) Skip(size int) int

Skip ignore the next size of bytes for encoding/decoding. It will panic If space not enough. It will return -1 if size <= 0.

func (*Decoder) String

func (decoder *Decoder) String() string

String decode a string value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Uint

func (decoder *Decoder) Uint() uint

Uint decode a uint value from Decoder buffer. It will panic if buffer is not enough. It use Uvarint() to decode as uvarint(1~10 bytes)

func (*Decoder) Uint16

func (decoder *Decoder) Uint16(packed bool) uint16

Uint16 decode a uint16 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Uint32

func (decoder *Decoder) Uint32(packed bool) uint32

Uint32 decode a uint32 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Uint64

func (decoder *Decoder) Uint64(packed bool) uint64

Uint64 decode a uint64 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Uint8

func (decoder *Decoder) Uint8() uint8

Uint8 decode a uint8 value from Decoder buffer. It will panic if buffer is not enough.

func (*Decoder) Uvarint

func (decoder *Decoder) Uvarint() (uint64, int)

Uvarint decode a uint64 value from Decoder buffer with varint(1~10 bytes). It will panic if buffer is not enough. It will return n <= 0 if varint error

func (*Decoder) Value

func (decoder *Decoder) Value(x interface{}) (err error)

Value decode an interface value from Encoder buffer. x must be interface of pointer for modify. It will return none-nil error if x contains unsupported types or buffer is not enough. It will check if x implements interface BinaryEncoder and use x.Encode first.

func (*Decoder) Varint

func (decoder *Decoder) Varint() (int64, int)

Varint decode an int64 value from Decoder buffer with varint(1~10 bytes). It will panic if buffer is not enough.

type Encoder

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

Encoder is used to encode go data to byte array.

Example
package main

import (
	"fmt"

	"github.com/vipally/binary"
)

func main() {
	encoder := binary.NewEncoder(100)

	encoder.Uint32(0x11223344, false)
	encoder.Varint(-5)
	encoder.String("hello")
	encodeResult := encoder.Buffer()
	fmt.Printf("%#v", encodeResult)

}
Output:

[]byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f}

func NewEncoder

func NewEncoder(size int) *Encoder

NewEncoder make a new Encoder object with buffer size.

func NewEncoderBuffer

func NewEncoderBuffer(buffer []byte) *Encoder

NewEncoderBuffer make a new Encoder object with buffer.

func NewEncoderEndian

func NewEncoderEndian(size int, endian Endian) *Encoder

NewEncoderEndian make a new Encoder object with buffer size and endian.

func (*Encoder) Bool

func (encoder *Encoder) Bool(x bool)

Bool encode a bool value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Buffer

func (cder *Encoder) Buffer() []byte

Buffer returns the byte slice that has been encoding/decoding.

func (*Encoder) Cap

func (cder *Encoder) Cap() int

Cap returns number total bytes of cder coder buffer.

func (*Encoder) Complex128

func (encoder *Encoder) Complex128(x complex128)

Complex128 encode a complex128 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Complex64

func (encoder *Encoder) Complex64(x complex64)

Complex64 encode a complex64 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Float32

func (encoder *Encoder) Float32(x float32)

Float32 encode a float32 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Float64

func (encoder *Encoder) Float64(x float64)

Float64 encode a float64 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Init

func (encoder *Encoder) Init(size int, endian Endian)

Init initialize Encoder with buffer size and endian.

func (*Encoder) Int

func (encoder *Encoder) Int(x int)

Int encode an int value to Encoder buffer. It will panic if buffer is not enough. It use Varint() to encode as varint(1~10 bytes)

func (*Encoder) Int16

func (encoder *Encoder) Int16(x int16, packed bool)

Int16 encode an int16 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Int32

func (encoder *Encoder) Int32(x int32, packed bool)

Int32 encode an int32 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Int64

func (encoder *Encoder) Int64(x int64, packed bool)

Int64 encode an int64 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Int8

func (encoder *Encoder) Int8(x int8)

Int8 encode an int8 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Len

func (cder *Encoder) Len() int

Len returns unmber of bytes that has been encoding/decoding.

func (*Encoder) Reset

func (cder *Encoder) Reset()

Reset move the read/write pointer to the beginning of buffer and set all reseted bytes to 0.

func (*Encoder) ResizeBuffer

func (encoder *Encoder) ResizeBuffer(size int) bool

ResizeBuffer confirm that len(buffer) >= size and alloc larger buffer if necessary It will call Reset to initial encoder state of buffer

func (*Encoder) Skip

func (cder *Encoder) Skip(size int) int

Skip ignore the next size of bytes for encoding/decoding and set skiped bytes to 0. It will panic if space not enough. It will return -1 if size <= 0.

func (*Encoder) String

func (encoder *Encoder) String(x string)

String encode a string value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Uint

func (encoder *Encoder) Uint(x uint)

Uint encode a uint value to Encoder buffer. It will panic if buffer is not enough. It use Uvarint() to encode as uvarint(1~10 bytes)

func (*Encoder) Uint16

func (encoder *Encoder) Uint16(x uint16, packed bool)

Uint16 encode a uint16 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Uint32

func (encoder *Encoder) Uint32(x uint32, packed bool)

Uint32 encode a uint32 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Uint64

func (encoder *Encoder) Uint64(x uint64, packed bool)

Uint64 encode a uint64 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Uint8

func (encoder *Encoder) Uint8(x uint8)

Uint8 encode a uint8 value to Encoder buffer. It will panic if buffer is not enough.

func (*Encoder) Uvarint

func (encoder *Encoder) Uvarint(x uint64) int

Uvarint encode a uint64 value to Encoder buffer with varint(1~10 bytes). It will panic if buffer is not enough.

func (*Encoder) Value

func (encoder *Encoder) Value(x interface{}) (err error)

Value encode an interface value to Encoder buffer. It will return none-nil error if x contains unsupported types or buffer is not enough. It will check if x implements interface BinaryEncoder and use x.Encode first.

func (*Encoder) Varint

func (encoder *Encoder) Varint(x int64) int

Varint encode an int64 value to Encoder buffer with varint(1~10 bytes). It will panic if buffer is not enough.

type Endian

type Endian interface {
	Uint16([]byte) uint16
	Uint32([]byte) uint32
	Uint64([]byte) uint64
	PutUint16([]byte, uint16)
	PutUint32([]byte, uint32)
	PutUint64([]byte, uint64)
	String() string
}

Endian is a ByteOrder specifies how to convert byte sequences into 16-, 32-, or 64-bit unsigned integers.

Jump to

Keyboard shortcuts

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