├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bench_test.go ├── binary_test.go ├── coder.go ├── coder_test.go ├── decoder.go ├── encoder.go ├── endian.go ├── example_test.go ├── export.go ├── func.go ├── struct.go ├── varint.go └── varint_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - tip 4 | before_install: 5 | - go get github.com/mattn/goveralls 6 | - go get golang.org/x/tools/cmd/cover 7 | #- go get github.com/alecthomas/gometalinter 8 | #- $HOME/gopath/bin/gometalinter --install --update 9 | - go get github.com/vipally/binary 10 | script: 11 | - go vet 12 | - go test 13 | - $HOME/gopath/bin/goveralls -repotoken X9dt3MTIoRZ1nTCVh5ueEJeGrPFDQr23z 14 | #- $HOME/gopath/bin/gometalinter ./... -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ally Dale 4 | Author : Ally Dale 5 | Site : https://github.com/vipally 6 | Origin : https://github.com/vipally/binary 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # binary 2 | 3 | ![Version][version-img] [![Build status][travis-img]][travis-url] [![Coverage Status][coverage-img]][coverage-url] [![Go Report Card][report-img]][report-url] [![GoDoc][doc-img]][doc-url] [![License][license-img]][license-url] 4 | 5 | *** 6 | 7 | Package binary is uesed to Encode/Decode between go data and byte slice. 8 | 9 | The main purpose of this package is to replace package "std.binary". 10 | 11 | Compare with other serialization package, this package is with full-feature as 12 | gob and protocol buffers, and with high-performance and lightweight as std.binary. 13 | 14 | It is designed as a common solution to easily encode/decode between go data and byte slice. 15 | 16 | It is recommended to use in net protocol serialization and go memory data serialization such as DB. 17 | 18 | *** 19 | 20 | ## Install 21 | 22 | ```bash 23 | $ go get -u github.com/vipally/binary 24 | ``` 25 | import( 26 | "github.com/vipally/binary" 27 | ) 28 | 29 | *** 30 | 31 | # Change log: 32 | ## v1.2.0 33 | 1.use field tag `binary:"packed"` to encode ints value as varint/uvarint 34 | for reged structs. 35 | 2.add method Encoder.ResizeBuffer. 36 | ## v1.1.0 37 | 1.fix issue#1 nil pointer encode/decode error. 38 | 2.pack 8 bool values as bits in one byte. 39 | 3.put one bool bit for pointer fields to check if it is a nil pointer. 40 | 4.rename Pack/Unpack to Encode/Decode. 41 | ## v1.0.0 42 | 1.full-type support like gob. 43 | 2.light-weight as std.binary. 44 | 3.high-performance as std.binary and gob. 45 | 4.encoding with fower bytes than std.binary and gob. 46 | 5.use RegStruct to improve performance of struct encoding/decoding. 47 | 6.take both advantages of std.binary and gob. 48 | 7.recommended using in net protocol serialization and DB serialization. 49 | 50 | # Todo: 51 | 1.[Encoder/Decoder].RegStruct to speed up local Coder. 52 | 2.[Encoder/Decoder].RegSerializer to speed up BinarySerializer search. 53 | 3.reg interface to using BinarySerializer interface. 54 | 55 | *** 56 | 57 | ## CopyRight 58 | 59 | CopyRight 2017 @Ally Dale. All rights reserved. 60 | 61 | Author : [Ally Dale(vipally@gmail.com)](mailto://vipally@gmail.com) 62 | 63 | Blog : [http://blog.csdn.net/vipally](http://blog.csdn.net/vipally) 64 | 65 | Site : [https://github.com/vipally](https://github.com/vipally) 66 | 67 | **** 68 | 69 | # 1. Support all serialize-able basic types: 70 | int, int8, int16, int32, int64, 71 | uint, uint8, uint16, uint32, uint64, 72 | float32, float64, complex64, complex128, 73 | bool, string, slice, array, map, struct. 74 | And their direct pointers. 75 | eg: *string, *struct, *map, *slice, *int32. 76 | 77 | # 2. [recommended usage] Use Encode/Decode to read/write memory buffer directly. 78 | ## Use RegStruct to improve struct encoding/decoding efficiency. 79 | type someRegedStruct struct { 80 | A int `binary:"ignore"` 81 | B string 82 | C uint 83 | } 84 | binary.RegStruct((*someRegedStruct)(nil)) 85 | 86 | If data implements interface BinaryEncoder, it will use data.Encode/data.Decode 87 | to encode/decode data. 88 | NOTE that data.Decode must implement on pointer receiever to enable modifying 89 | receiever.Even though Size/Encode of data can implement on non-pointer receiever, 90 | binary.Encode(&data, nil) is required if data has implement interface BinaryEncoder. 91 | binary.Encode(data, nil) will probably NEVER use BinaryEncoder methods to Encode/Decode 92 | data. 93 | eg: 94 | 95 | import "github.com/vipally/binary" 96 | 97 | //1.Encode with default buffer 98 | if bytes, err := binary.Encode(&data, nil); err==nil{ 99 | //... 100 | } 101 | 102 | //2.Encode with existing buffer 103 | size := binary.Sizeof(data) 104 | buffer := make([]byte, size) 105 | if bytes, err := binary.Encode(&data, buffer); err==nil{ 106 | //... 107 | } 108 | 109 | //3.Decode from buffer 110 | if err := binary.Decode(bytes, &data); err==nil{ 111 | //... 112 | } 113 | 114 | # 3. [advanced usage] Encoder/Decoder are exported types aviable for encoding/decoding. 115 | eg: 116 | encoder := binary.NewEncoder(bufferSize) 117 | encoder.Uint32(u32) 118 | encoder.String(str) 119 | encodeResult := encoder.Buffer() 120 | 121 | decoder := binary.NewDecoder(buffer) 122 | u32 := decoder.Uint32() 123 | str := decoder.String() 124 | 125 | # 4. Put an extra length field(uvarint,1~10 bytes) before string, slice, array, map. 126 | eg: 127 | var s string = "hello" 128 | will be encoded as: 129 | []byte{0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 130 | 131 | # 5. Pack bool array with bits. 132 | eg: 133 | []bool{true, true, true, false, true, true, false, false, true} 134 | will be encoded as: 135 | []byte{0x9, 0x37, 0x1} 136 | 137 | # 6. Hide struct field when encoding/decoding. 138 | Only encode/decode exported fields. 139 | Support using field tag `binary:"ignore"` to disable encode/decode fields. 140 | eg: 141 | type S struct{ 142 | A uint32 143 | b uint32 144 | _ uint32 145 | C uint32 `binary:"ignore"` 146 | } 147 | Only field "A" will be encode/decode. 148 | 149 | # 7. Auto allocate for slice, map and pointer. 150 | eg: 151 | type S struct{ 152 | A *uint32 153 | B *string 154 | C *[]uint8 155 | D []uint32 156 | } 157 | It will new pointers for fields "A, B, C", 158 | and make new slice for fields "*C, D" when decode. 159 | 160 | # 8. int/uint values will be encoded as varint/uvarint(1~10 bytes). 161 | eg: 162 | uint(1) will be encoded as: []byte{0x1} 163 | uint(128) will be encoded as: []byte{0x80, 0x1} 164 | uint(32765) will be encoded as: []byte{0xfd, 0xff, 0x1} 165 | int(-5) will be encoded as: []byte{0x9} 166 | int(-65) will be encoded as: []byte{0x81, 0x1} 167 | 168 | # 9. Test results. 169 | ## Enncoding size(see example of Sizeof). 170 | Encoding bytes is much shorter than std.binary and gob. 171 | 172 | var s struct { 173 | Int8 int8 174 | Int16 int16 175 | Int32 int32 176 | Int64 int64 177 | Uint8 uint8 178 | Uint16 uint16 179 | Uint32 uint32 180 | Uint64 uint64 181 | Float32 float32 182 | Float64 float64 183 | Complex64 complex64 184 | Complex128 complex128 185 | Array [10]uint8 186 | Bool bool 187 | BoolArray [100]bool 188 | Uint32Array [10]uint32 189 | } 190 | 191 | Output: 192 | Sizeof(s) = 133 193 | std.Size(s)= 217 194 | gob.Size(s)= 412 195 | 196 | ## Benchmark test result. 197 | Pack/Unpack unregisted struct is a little slower(80%) than std.binary.Read/std.binary.Write 198 | Pack/Unpack registed struct is much faster(200%) than std.binary.Read/std.binary.Write 199 | Pack/Unpack int array is much faster(230%) than std.binary.Read/std.binary.Write 200 | Pack/Unpack string is a little faster(140%) than gob.Encode/gob.Decode 201 | 202 | BenchmarkGobEncodeStruct 1000000 1172 ns/op 300.32 MB/s 203 | BenchmarkStdWriteStruct 1000000 3154 ns/op 23.78 MB/s 204 | BenchmarkWriteStruct 500000 3954 ns/op 18.71 MB/s 205 | BenchmarkWriteRegedStruct 1000000 1627 ns/op 45.48 MB/s 206 | BenchmarkPackStruct 500000 3642 ns/op 20.32 MB/s 207 | BenchmarkPackRegedStruct 1000000 1542 ns/op 47.99 MB/s 208 | BenchmarkGobDecodeStruct 3000000 651 ns/op 540.40 MB/s 209 | BenchmarkStdReadStruct 1000000 2008 ns/op 37.35 MB/s 210 | BenchmarkReadStruct 500000 2386 ns/op 31.01 MB/s 211 | BenchmarkReadRegedStruct 1000000 1194 ns/op 61.97 MB/s 212 | BenchmarkUnackStruct 1000000 2293 ns/op 32.27 MB/s 213 | BenchmarkUnpackRegedStruct 2000000 935 ns/op 79.14 MB/s 214 | BenchmarkGobEncodeInt1000 100000 22871 ns/op 219.58 MB/s 215 | BenchmarkStdWriteInt1000 30000 49502 ns/op 80.80 MB/s 216 | BenchmarkWriteInt1000 50000 26001 ns/op 153.91 MB/s 217 | BenchmarkPackInt1000 100000 21601 ns/op 185.27 MB/s 218 | BenchmarkStdReadInt1000 30000 44035 ns/op 90.84 MB/s 219 | BenchmarkReadInt1000 50000 29761 ns/op 134.47 MB/s 220 | BenchmarkUnackInt1000 50000 25001 ns/op 160.07 MB/s 221 | BenchmarkGobEncodeString 3000000 444 ns/op 301.56 MB/s 222 | BenchmarkStdWriteString unsupported 223 | BenchmarkWriteString 3000000 455 ns/op 285.49 MB/s 224 | BenchmarkPackString 5000000 337 ns/op 385.05 MB/s 225 | BenchmarkGobDecodeString 1000000 1266 ns/op 105.84 MB/s 226 | BenchmarkStdReadString unsupported 227 | BenchmarkReadString 3000000 550 ns/op 236.06 MB/s 228 | BenchmarkUnackString 5000000 298 ns/op 435.92 MB/s 229 | 230 | # With full-datatype support like gob. 231 | Followed struct fullStruct is an aviable type that contains all supported types. 232 | Which is not valid for std.binary. 233 | 234 | type fullStruct struct { 235 | Int8 int8 236 | Int16 int16 237 | Int32 int32 238 | Int64 int64 239 | Uint8 uint8 240 | Uint16 uint16 241 | Uint32 uint32 242 | Uint64 uint64 243 | Float32 float32 244 | Float64 float64 245 | Complex64 complex64 246 | Complex128 complex128 247 | Array [4]uint8 248 | Bool bool 249 | BoolArray [9]bool 250 | 251 | LittleStruct littleStruct 252 | PLittleStruct *littleStruct 253 | String string 254 | PString *string 255 | PInt32 *int32 256 | Slice []*littleStruct 257 | PSlice *[]*string 258 | Float64Slice []float64 259 | BoolSlice []bool 260 | Uint32Slice []uint32 261 | Map map[string]*littleStruct 262 | Map2 map[string]uint16 263 | IntSlice []int 264 | UintSlice []uint 265 | } 266 | 267 | # Do not supported types. 268 | Followed struct TDoNotSupport is an invalid type that every field is invalid. 269 | 270 | type TDoNotSupport struct { 271 | DeepPointer **uint32 272 | Uintptr uintptr 273 | UnsafePointer unsafe.Pointer 274 | Ch chan bool 275 | Map map[uintptr]uintptr 276 | Map2 map[int]uintptr 277 | Map3 map[uintptr]int 278 | Slice []uintptr 279 | Array [2]uintptr 280 | Array2 [2][2]uintptr 281 | Array3 [2]struct{ A uintptr } 282 | Func func() 283 | Struct struct { 284 | PStruct *struct { 285 | PPUintptr **uintptr 286 | } 287 | } 288 | } 289 | 290 | # License. 291 | Under MIT license. 292 | 293 | Copyright (c) 2017 Ally Dale 294 | Author : Ally Dale 295 | Site : https://github.com/vipally 296 | Origin : https://github.com/vipally/binary 297 | 298 | [travis-img]: https://travis-ci.org/vipally/binary.svg?branch=master 299 | [travis-url]: https://travis-ci.org/vipally/binary 300 | [coverage-img]: https://coveralls.io/repos/github/vipally/binary/badge.svg?branch=master 301 | [coverage-url]: https://coveralls.io/github/vipally/binary?branch=master 302 | [license-img]: http://img.shields.io/badge/license-MIT-green.svg?style=flat-square 303 | [license-url]: http://opensource.org/licenses/MIT 304 | [doc-img2]: http://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square 305 | [doc-img]: https://godoc.org/github.com/vipally/binary?status.svg 306 | [doc-url]: https://godoc.org/github.com/vipally/binary 307 | [report-img]: https://goreportcard.com/badge/github.com/vipally/binary 308 | [report-url]: https://goreportcard.com/report/github.com/vipally/binary 309 | [version-img]: https://img.shields.io/badge/version-1.2.0-green.svg 310 | 311 | -------------------------------------------------------------------------------- /bench_test.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "bytes" 5 | std "encoding/binary" 6 | "encoding/gob" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | type regedStruct struct { 12 | Int8 int8 13 | Int16 int16 14 | Int32 int32 15 | Int64 int64 16 | Uint8 uint8 17 | Uint16 uint16 18 | Uint32 uint32 19 | Uint64 uint64 20 | Float32 float32 21 | Float64 float64 22 | Complex64 complex64 23 | Complex128 complex128 24 | Array [4]uint8 25 | Bool bool 26 | BoolArray [4]bool 27 | } 28 | 29 | var ( 30 | buff = make([]byte, 8192) 31 | buffer = bytes.NewBuffer(buff[:0]) 32 | 33 | wStruct Struct 34 | 35 | u32Array1000 [1000]uint32 36 | u32Array1000W [1000]uint32 37 | 38 | caseStdReadWrite string 39 | 40 | str = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 41 | strW string 42 | ) 43 | 44 | func init() { 45 | RegStruct((*regedStruct)(nil)) 46 | for i := len(u32Array1000) - 1; i >= 0; i-- { 47 | u32Array1000[i] = uint32(i)*7368787 + 2750159 //rand number 48 | } 49 | } 50 | 51 | //////////////////////////////////////////////////////////////////Struct 52 | func BenchmarkGobEncodeStruct(b *testing.B) { 53 | data := _struct 54 | testBenchGobEncode(b, data, "BenchmarkGobEncodeStruct") 55 | } 56 | func BenchmarkStdWriteStruct(b *testing.B) { 57 | data := _struct 58 | testBenchStdWrite(b, data, "BenchmarkStdWriteStruct") 59 | } 60 | func BenchmarkWriteStruct(b *testing.B) { 61 | data := _struct 62 | testBenchWrite(b, data, "BenchmarkWriteStruct") 63 | } 64 | func BenchmarkWriteRegedStruct(b *testing.B) { 65 | data := regedStruct(_struct) 66 | testBenchWrite(b, data, "BenchmarkWriteRegedStruct") 67 | } 68 | func BenchmarkEncodeStruct(b *testing.B) { 69 | data := _struct 70 | testBenchEncode(b, data, "BenchmarkEncodeStruct") 71 | } 72 | func BenchmarkEncodeRegedStruct(b *testing.B) { 73 | data := regedStruct(_struct) 74 | testBenchEncode(b, data, "BenchmarkEncodeRegedStruct") 75 | } 76 | func BenchmarkGobDecodeStruct(b *testing.B) { 77 | data := _struct 78 | testBenchGobDecode(b, &data, &wStruct, "BenchmarkGobDecodeStruct") 79 | } 80 | func BenchmarkStdReadStruct(b *testing.B) { 81 | data := _struct 82 | testBenchStdRead(b, &data, &wStruct, "BenchmarkStdReadStruct") 83 | } 84 | func BenchmarkReadStruct(b *testing.B) { 85 | data := _struct 86 | testBenchRead(b, &data, &wStruct, "BenchmarkReadStruct") 87 | } 88 | func BenchmarkReadRegedStruct(b *testing.B) { 89 | data := regedStruct(_struct) 90 | dataC := regedStruct(wStruct) 91 | testBenchRead(b, &data, &dataC, "BenchmarkReadRegedStruct") 92 | } 93 | func BenchmarkDecodeStruct(b *testing.B) { 94 | data := _struct 95 | testBenchDecode(b, &data, &wStruct, "BenchmarkDecodeStruct") 96 | } 97 | func BenchmarkDecodeRegedStruct(b *testing.B) { 98 | data := regedStruct(_struct) 99 | dataC := regedStruct(wStruct) 100 | testBenchDecode(b, &data, &dataC, "BenchmarkDecodeRegedStruct") 101 | } 102 | 103 | //////////////////////////////////////////////////////////////////Int1000 104 | func BenchmarkGobEncodeInt1000(b *testing.B) { 105 | data := u32Array1000 106 | testBenchGobEncode(b, data, "BenchmarkGobEncodeInt1000") 107 | } 108 | func BenchmarkStdWriteInt1000(b *testing.B) { 109 | data := u32Array1000 110 | testBenchStdWrite(b, data, "BenchmarkStdWriteInt1000") 111 | } 112 | func BenchmarkWriteInt1000(b *testing.B) { 113 | data := u32Array1000 114 | testBenchWrite(b, data, "BenchmarkWriteInt1000") 115 | } 116 | func BenchmarkEncodeInt1000(b *testing.B) { 117 | data := u32Array1000 118 | testBenchEncode(b, data, "BenchmarkEncodeInt1000") 119 | } //BUG: this case will fail 120 | //func BenchmarkGobDecodeInt1000(b *testing.B) { 121 | // data := u32Array1000 122 | // testBenchGobDecode(b, &data, &u32Array1000W, "BenchmarkGobDecodeInt1000") 123 | //} 124 | func BenchmarkStdReadInt1000(b *testing.B) { 125 | data := u32Array1000 126 | testBenchStdRead(b, &data, &u32Array1000W, "BenchmarkStdReadInt1000") 127 | } 128 | func BenchmarkReadInt1000(b *testing.B) { 129 | data := u32Array1000 130 | testBenchRead(b, &data, &u32Array1000W, "BenchmarkReadInt1000") 131 | } 132 | func BenchmarkUnackInt1000(b *testing.B) { 133 | data := u32Array1000 134 | testBenchDecode(b, &data, &u32Array1000W, "BenchmarkUnackInt1000") 135 | } 136 | 137 | //////////////////////////////////////////////////////////////////String 138 | func BenchmarkGobEncodeString(b *testing.B) { 139 | data := str 140 | testBenchGobEncode(b, data, "BenchmarkGobEncodeString") 141 | } 142 | func BenchmarkStdWriteString(b *testing.B) { 143 | data := str 144 | testBenchStdWrite(b, data, "BenchmarkStdWriteString") 145 | } 146 | func BenchmarkWriteString(b *testing.B) { 147 | data := str 148 | testBenchWrite(b, data, "BenchmarkWriteString") 149 | } 150 | func BenchmarkEncodeString(b *testing.B) { 151 | data := str 152 | testBenchEncode(b, data, "BenchmarkEncodeString") 153 | } 154 | func BenchmarkGobDecodeString(b *testing.B) { 155 | data := str 156 | testBenchGobDecode(b, &data, &strW, "BenchmarkGobDecodeString") 157 | } 158 | func BenchmarkStdReadString(b *testing.B) { 159 | data := str 160 | testBenchStdRead(b, &data, &strW, "BenchmarkStdReadString") 161 | } 162 | func BenchmarkReadString(b *testing.B) { 163 | data := str 164 | testBenchRead(b, &data, &strW, "BenchmarkReadString") 165 | } 166 | func BenchmarkUnackString(b *testing.B) { 167 | data := str 168 | testBenchDecode(b, &data, &strW, "BenchmarkUnackString") 169 | } 170 | 171 | //func newSame(v reflect.Value) (value reflect.Value) { 172 | // vv := reflect.Indirect(v) 173 | // t := vv.Type() 174 | // switch t.Kind() { 175 | // case reflect.Bool, reflect.Int8, reflect.Uint8, reflect.Int16, 176 | // reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, 177 | // reflect.Uint64, reflect.Float32, reflect.Float64, reflect.Complex64, 178 | // reflect.Complex128, reflect.String, reflect.Array, reflect.Struct: 179 | // value = reflect.New(t) 180 | // case reflect.Slice: 181 | // value = reflect.MakeSlice(t, 0, 0).Addr() //make a default slice 182 | // } 183 | // return 184 | //} 185 | 186 | func testBenchGobEncode(b *testing.B, data interface{}, caseName string) { 187 | buffer.Reset() 188 | coder := gob.NewEncoder(buffer) 189 | err := coder.Encode(data) 190 | b.SetBytes(int64(buffer.Len())) 191 | if err != nil { 192 | b.Error(err) 193 | } 194 | b.ResetTimer() 195 | for i := 0; i < b.N; i++ { 196 | buffer.Reset() 197 | coder.Encode(data) 198 | } 199 | b.StopTimer() 200 | } 201 | func testBenchStdWrite(b *testing.B, data interface{}, caseName string) { 202 | s := std.Size(data) 203 | if s <= 0 { 204 | if caseStdReadWrite != caseName { 205 | caseStdReadWrite = caseName 206 | println(caseName, "unsupported ") 207 | } 208 | return 209 | } 210 | buffer.Reset() 211 | b.SetBytes(int64(s)) 212 | b.ResetTimer() 213 | for i := 0; i < b.N; i++ { 214 | buffer.Reset() 215 | std.Write(buffer, std.LittleEndian, data) 216 | } 217 | b.StopTimer() 218 | } 219 | func testBenchWrite(b *testing.B, data interface{}, caseName string) { 220 | b.SetBytes(int64(Sizeof(data))) 221 | buffer.Reset() 222 | b.ResetTimer() 223 | for i := 0; i < b.N; i++ { 224 | buffer.Reset() 225 | Write(buffer, std.LittleEndian, data) 226 | } 227 | b.StopTimer() 228 | } 229 | func testBenchEncode(b *testing.B, data interface{}, caseName string) { 230 | b.SetBytes(int64(Sizeof(data))) 231 | b.ResetTimer() 232 | for i := 0; i < b.N; i++ { 233 | Encode(data, buff) 234 | } 235 | b.StopTimer() 236 | } 237 | 238 | func testBenchGobDecode(b *testing.B, data, w interface{}, caseName string) { 239 | bsr := &byteSliceReader{} 240 | buffer.Reset() 241 | encoder := gob.NewEncoder(buffer) 242 | err := encoder.Encode(data) 243 | if err != nil { 244 | b.Error(caseName, err) 245 | } 246 | b.SetBytes(int64(buffer.Len())) 247 | 248 | b.ResetTimer() 249 | buf := buffer.Bytes() 250 | bsr.remain = buf 251 | decoder := gob.NewDecoder(bsr) 252 | decoder.Decode(w) 253 | for i := 0; i < b.N; i++ { 254 | bsr.remain = buf 255 | decoder.Decode(w) 256 | } 257 | b.StopTimer() 258 | if b.N > 0 && !reflect.DeepEqual(data, w) { 259 | b.Fatalf("%s doesn't match:\ngot %#v;\nwant %#v", caseName, w, data) 260 | } 261 | } 262 | func testBenchStdRead(b *testing.B, data, w interface{}, caseName string) { 263 | s := std.Size(data) 264 | if s <= 0 { 265 | if caseStdReadWrite != caseName { 266 | caseStdReadWrite = caseName 267 | println(caseName, "unsupported ") 268 | } 269 | return 270 | } 271 | bsr := &byteSliceReader{} 272 | buffer.Reset() 273 | err := std.Write(buffer, std.LittleEndian, data) 274 | if err != nil { 275 | b.Error(caseName, err) 276 | } 277 | b.SetBytes(int64(len(buffer.Bytes()))) 278 | 279 | b.ResetTimer() 280 | bsr.remain = buffer.Bytes() 281 | std.Read(bsr, std.LittleEndian, w) 282 | for i := 0; i < b.N; i++ { 283 | bsr.remain = buffer.Bytes() 284 | std.Read(bsr, std.LittleEndian, w) 285 | } 286 | b.StopTimer() 287 | if b.N > 0 && !reflect.DeepEqual(data, w) { 288 | b.Fatalf("%s doesn't match:\ngot %#v;\nwant %#v", caseName, w, data) 289 | } 290 | } 291 | func testBenchRead(b *testing.B, data, w interface{}, caseName string) { 292 | bsr := &byteSliceReader{} 293 | buffer.Reset() 294 | err := Write(buffer, DefaultEndian, data) 295 | if err != nil { 296 | b.Error(caseName, err) 297 | } 298 | b.SetBytes(int64(len(buffer.Bytes()))) 299 | 300 | b.ResetTimer() 301 | bsr.remain = buffer.Bytes() 302 | Read(bsr, DefaultEndian, w) 303 | for i := 0; i < b.N; i++ { 304 | bsr.remain = buffer.Bytes() 305 | Read(bsr, DefaultEndian, w) 306 | } 307 | b.StopTimer() 308 | if b.N > 0 && !reflect.DeepEqual(data, w) { 309 | b.Fatalf("%s doesn't match:\ngot %#v;\nwant %#v", caseName, w, data) 310 | } 311 | } 312 | func testBenchDecode(b *testing.B, data, w interface{}, caseName string) { 313 | buf, err := Encode(data, buff) 314 | if err != nil { 315 | b.Error(caseName, err) 316 | } 317 | b.SetBytes(int64(len(buf))) 318 | 319 | b.ResetTimer() 320 | for i := 0; i < b.N; i++ { 321 | Decode(buf, w) 322 | } 323 | b.StopTimer() 324 | if b.N > 0 && !reflect.DeepEqual(data, w) { 325 | b.Fatalf("%s doesn't match:\ngot %#v;\nwant %#v", caseName, w, data) 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /binary_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // this file is the test cases from std.binary 6 | 7 | package binary 8 | 9 | import ( 10 | "bytes" 11 | "io" 12 | "math" 13 | "reflect" 14 | "testing" 15 | ) 16 | 17 | type Struct struct { 18 | Int8 int8 19 | Int16 int16 20 | Int32 int32 21 | Int64 int64 22 | Uint8 uint8 23 | Uint16 uint16 24 | Uint32 uint32 25 | Uint64 uint64 26 | Float32 float32 27 | Float64 float64 28 | Complex64 complex64 29 | Complex128 complex128 30 | Array [4]uint8 31 | Bool bool 32 | BoolArray [4]bool 33 | } 34 | 35 | var _struct = Struct{ 36 | 0x01, //Int8 37 | 0x0203, //Int16 38 | 0x04050607, //Int32 39 | 0x08090a0b0c0d0e0f, //Int64 40 | 0x10, //Uint8 41 | 0x1112, //Uint16 42 | 0x13141516, //Uint32 43 | 0x1718191a1b1c1d1e, //Uint64 44 | 45 | math.Float32frombits(0x1f202122), //Float32 46 | math.Float64frombits(0x232425262728292a), //Float64 47 | complex( 48 | math.Float32frombits(0x2b2c2d2e), 49 | math.Float32frombits(0x2f303132), 50 | ), //Complex64 51 | complex( 52 | math.Float64frombits(0x333435363738393a), 53 | math.Float64frombits(0x3b3c3d3e3f404142), 54 | ), //Complex128 55 | 56 | [4]uint8{0x43, 0x44, 0x45, 0x46}, //Array 57 | 58 | true, //Bool 59 | [4]bool{true, false, true, false}, //BoolArray 60 | } 61 | 62 | var big = []byte{ 63 | 1, 64 | 2, 3, 65 | 4, 5, 6, 7, 66 | 8, 9, 10, 11, 12, 13, 14, 15, 67 | 16, 68 | 17, 18, 69 | 19, 20, 21, 22, 70 | 23, 24, 25, 26, 27, 28, 29, 30, 71 | 72 | 31, 32, 33, 34, 73 | 35, 36, 37, 38, 39, 40, 41, 42, 74 | 43, 44, 45, 46, 47, 48, 49, 50, 75 | 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 76 | 77 | 4, 67, 68, 69, 70, 78 | 79 | 1, 80 | 4, 5, 81 | } 82 | 83 | var little = []byte{ 84 | 1, 85 | 3, 2, 86 | 7, 6, 5, 4, 87 | 15, 14, 13, 12, 11, 10, 9, 8, 88 | 16, 89 | 18, 17, 90 | 22, 21, 20, 19, 91 | 30, 29, 28, 27, 26, 25, 24, 23, 92 | 93 | 34, 33, 32, 31, 94 | 42, 41, 40, 39, 38, 37, 36, 35, 95 | 46, 45, 44, 43, 50, 49, 48, 47, 96 | 58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59, 97 | 98 | 4, 67, 68, 69, 70, 99 | 100 | 1, 101 | 4, 5, 102 | } 103 | 104 | var src = []byte{2, 1, 2, 3, 4, 5, 6, 7, 8} 105 | var res = []int32{0x01020304, 0x05060708} 106 | 107 | func checkResult(t *testing.T, dir string, order Endian, err error, have, want interface{}) { 108 | if err != nil { 109 | t.Errorf("%v %v: %v", dir, order, err) 110 | return 111 | } 112 | if !reflect.DeepEqual(have, want) { 113 | t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want) 114 | } 115 | } 116 | 117 | func testRead(t *testing.T, order Endian, b []byte, s1 interface{}) { 118 | var s2 Struct 119 | err := Read(bytes.NewReader(b), order, &s2) 120 | checkResult(t, "Read", order, err, s2, s1) 121 | } 122 | 123 | func testWrite(t *testing.T, order Endian, b []byte, s1 interface{}) { 124 | buf := new(bytes.Buffer) 125 | err := Write(buf, order, s1) 126 | checkResult(t, "Write", order, err, buf.Bytes(), b) 127 | } 128 | 129 | func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, _struct) } 130 | func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, _struct) } 131 | func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &_struct) } 132 | 133 | func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, _struct) } 134 | func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, _struct) } 135 | func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &_struct) } 136 | 137 | func TestReadSlice(t *testing.T) { 138 | slice := make([]int32, 2) 139 | err := Read(bytes.NewReader(src), BigEndian, &slice) 140 | checkResult(t, "ReadSlice", BigEndian, err, slice, res) 141 | } 142 | 143 | func TestWriteSlice(t *testing.T) { 144 | buf := new(bytes.Buffer) 145 | err := Write(buf, BigEndian, res) 146 | checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src) 147 | } 148 | 149 | func TestReadBool(t *testing.T) { 150 | var ( 151 | res bool 152 | err error 153 | ) 154 | err = Read(bytes.NewReader([]byte{0}), BigEndian, &res) 155 | checkResult(t, "ReadBool", BigEndian, err, res, false) 156 | res = false 157 | err = Read(bytes.NewReader([]byte{1}), BigEndian, &res) 158 | checkResult(t, "ReadBool", BigEndian, err, res, true) 159 | res = false 160 | type boolSet struct { 161 | A bool 162 | B byte 163 | C bool 164 | } 165 | var boolSet1 boolSet 166 | var boolSet2 = boolSet{false, 15, true} 167 | err = Read(bytes.NewReader([]byte{2, 15}), BigEndian, &boolSet1) 168 | checkResult(t, "ReadBool", BigEndian, err, boolSet1, boolSet2) 169 | } 170 | 171 | func TestReadBoolSlice(t *testing.T) { 172 | slice := make([]bool, 4) 173 | err := Read(bytes.NewReader([]byte{4, 14}), BigEndian, &slice) 174 | checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true}) 175 | } 176 | 177 | // Addresses of arrays are easier to manipulate with reflection than are slices. 178 | var intArrays = []interface{}{ 179 | &[100]int8{}, 180 | &[100]int16{}, 181 | &[100]int32{}, 182 | &[100]int64{}, 183 | &[100]uint8{}, 184 | &[100]uint16{}, 185 | &[100]uint32{}, 186 | &[100]uint64{}, 187 | } 188 | 189 | func TestSliceRoundTrip(t *testing.T) { 190 | buf := new(bytes.Buffer) 191 | for _, array := range intArrays { 192 | src := reflect.ValueOf(array).Elem() 193 | unsigned := false 194 | switch src.Index(0).Kind() { 195 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 196 | unsigned = true 197 | } 198 | for i := 0; i < src.Len(); i++ { 199 | if unsigned { 200 | src.Index(i).SetUint(uint64(i * 0x07654321)) 201 | } else { 202 | src.Index(i).SetInt(int64(i * 0x07654321)) 203 | } 204 | } 205 | buf.Reset() 206 | srcSlice := src.Slice(0, src.Len()) 207 | err := Write(buf, BigEndian, srcSlice.Interface()) 208 | if err != nil { 209 | t.Fatal(err) 210 | } 211 | dst := reflect.New(src.Type()) 212 | err = Read(buf, BigEndian, dst.Interface()) 213 | if err != nil { 214 | t.Fatal(err) 215 | } 216 | if !reflect.DeepEqual(src.Interface(), dst.Elem().Interface()) { 217 | t.Fatal(src) 218 | } 219 | } 220 | } 221 | 222 | func TestDonotSupportedType(t *testing.T) { 223 | buf := new(bytes.Buffer) 224 | ts := doNotSupportTypes 225 | if err := Write(buf, BigEndian, ts); err == nil { 226 | t.Errorf("WriteDonotSupportedType: have err == nil, want non-nil") 227 | } 228 | 229 | tv := reflect.Indirect(reflect.ValueOf(&ts)) 230 | for i, n := 0, tv.NumField(); i < n; i++ { 231 | // if Sizeof(tv.Field(i).Interface()) >= 0 { 232 | // panic(tv.Field(i)) 233 | // } 234 | if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil { 235 | t.Errorf("Write DonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) 236 | } else { 237 | //println(err.Error()) 238 | } 239 | 240 | if err := Read(buf, BigEndian, tv.Field(i).Addr().Interface()); err == nil { 241 | t.Errorf("Read DonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) 242 | } else { 243 | //println(err.Error()) 244 | } 245 | } 246 | } 247 | 248 | type BlankFields struct { 249 | A uint32 250 | _ int32 251 | B float64 252 | _ [4]int16 253 | C byte 254 | _ [7]byte 255 | _ struct { 256 | f [8]float32 257 | } 258 | } 259 | 260 | type BlankFieldsProbe struct { 261 | A uint32 262 | P0 int32 `binary:"ignore"` 263 | B float64 264 | P1 [4]int16 `binary:"ignore"` 265 | C byte 266 | P2 [7]byte `binary:"ignore"` 267 | P3 struct { 268 | F [8]float32 269 | } `binary:"ignore"` 270 | } 271 | 272 | func TestBlankFields(t *testing.T) { 273 | buf := new(bytes.Buffer) 274 | b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42} 275 | if err := Write(buf, LittleEndian, &b1); err != nil { 276 | t.Error(err) 277 | } 278 | 279 | // zero values must have been written for blank fields 280 | var p BlankFieldsProbe 281 | if err := Read(buf, LittleEndian, &p); err != nil { 282 | t.Error(err) 283 | } 284 | 285 | // quick test: only check first value of slices 286 | if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 { 287 | t.Errorf("non-zero values for originally blank fields: %#v", p) 288 | } 289 | 290 | // write p and see if we can probe only some fields 291 | if err := Write(buf, LittleEndian, &p); err != nil { 292 | t.Error(err) 293 | } 294 | 295 | // read should ignore blank fields in b2 296 | var b2 BlankFields 297 | if err := Read(buf, LittleEndian, &b2); err != nil { 298 | t.Error(err) 299 | } 300 | if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C { 301 | t.Errorf("%#v != %#v", b1, b2) 302 | } 303 | } 304 | 305 | //************************************************************************************ 306 | // Different form std.binary, unexported filed will be ignored when encoding/decoding. 307 | // So TestUnexportedRead is not suitable for this package. 308 | //************************************************************************************ 309 | 310 | //// An attempt to read into a struct with an unexported field will 311 | //// panic. This is probably not the best choice, but at this point 312 | //// anything else would be an API change. 313 | // 314 | //type Unexported struct { 315 | // a int32 316 | //} 317 | // 318 | //func TestUnexportedRead(t *testing.T) { 319 | // var buf bytes.Buffer 320 | // u1 := Unexported{a: 1} 321 | // if err := Write(&buf, LittleEndian, &u1); err != nil { 322 | // t.Fatal(err) 323 | // } 324 | // 325 | // defer func() { 326 | // if recover() == nil { 327 | // t.Fatal("did not panic") 328 | // } 329 | // }() 330 | // var u2 Unexported 331 | // Read(&buf, LittleEndian, &u2) 332 | //} 333 | 334 | func TestReadErrorMsg(t *testing.T) { 335 | var buf bytes.Buffer 336 | read := func(data interface{}, nonPointer bool) { 337 | err := Read(&buf, LittleEndian, data) 338 | want := "binary.Decoder.Value: unsupported type " + reflect.TypeOf(data).String() 339 | if nonPointer { 340 | want = "binary.Decoder.Value: non-pointer type " + reflect.TypeOf(data).String() 341 | } 342 | if err == nil { 343 | t.Errorf("%T: got no error; want %q", data, want) 344 | return 345 | } 346 | if got := err.Error(); got != want { 347 | t.Errorf("%T: got %q; want %q", data, got, want) 348 | } 349 | } 350 | i := uintptr(0) 351 | read(&i, false) 352 | s := new(struct{}) 353 | read(*s, true) 354 | read(&s, false) 355 | p := &s 356 | read(&p, false) 357 | } 358 | 359 | func TestReadTruncated(t *testing.T) { 360 | var data = []byte{0x4, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf} 361 | 362 | var b1 = make([]int32, 4) 363 | var b2 struct { 364 | A0, A, B, C, D byte 365 | E int32 366 | F float64 367 | } 368 | 369 | for i := 0; i <= len(data); i++ { 370 | var errWant error 371 | switch i { 372 | case 0: 373 | errWant = io.ErrUnexpectedEOF 374 | case len(data): 375 | errWant = nil 376 | default: 377 | errWant = io.ErrUnexpectedEOF 378 | } 379 | 380 | if err := Read(bytes.NewReader(data[:i]), LittleEndian, &b1); err != errWant { 381 | t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant) 382 | } 383 | if err := Read(bytes.NewReader(data[:i]), LittleEndian, &b2); err != errWant { 384 | t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant) 385 | } 386 | } 387 | } 388 | 389 | func testUint64SmallSliceLengthPanics() (panicked bool) { 390 | defer func() { 391 | panicked = recover() != nil 392 | }() 393 | b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} 394 | LittleEndian.Uint64(b[:4]) 395 | return false 396 | } 397 | 398 | func testPutUint64SmallSliceLengthPanics() (panicked bool) { 399 | defer func() { 400 | panicked = recover() != nil 401 | }() 402 | b := [8]byte{} 403 | LittleEndian.PutUint64(b[:4], 0x0102030405060708) 404 | return false 405 | } 406 | 407 | func TestEarlyBoundsChecks(t *testing.T) { 408 | if !testUint64SmallSliceLengthPanics() { 409 | t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't") 410 | } 411 | if !testPutUint64SmallSliceLengthPanics() { 412 | t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't") 413 | } 414 | } 415 | 416 | type byteSliceReader struct { 417 | remain []byte 418 | } 419 | 420 | func (br *byteSliceReader) Read(p []byte) (int, error) { 421 | n := copy(p, br.remain) 422 | br.remain = br.remain[n:] 423 | return n, nil 424 | } 425 | 426 | //func BenchmarkReadSlice1000Int32s(b *testing.B) { 427 | // bsr := &byteSliceReader{} 428 | // slice := make([]int32, 1000) 429 | // buf := make([]byte, len(slice)*4) 430 | // b.SetBytes(int64(len(buf))) 431 | // b.ResetTimer() 432 | // for i := 0; i < b.N; i++ { 433 | // bsr.remain = buf 434 | // Read(bsr, BigEndian, slice) 435 | // } 436 | //} 437 | 438 | //func BenchmarkReadStruct(b *testing.B) { 439 | // bsr := &byteSliceReader{} 440 | // var buf bytes.Buffer 441 | // Write(&buf, BigEndian, &s) 442 | // b.SetBytes(int64(sizeofValue(reflect.ValueOf(s)))) 443 | // t := s 444 | // b.ResetTimer() 445 | // for i := 0; i < b.N; i++ { 446 | // bsr.remain = buf.Bytes() 447 | // Read(bsr, BigEndian, &t) 448 | // } 449 | // b.StopTimer() 450 | // if b.N > 0 && !reflect.DeepEqual(s, t) { 451 | // b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s) 452 | // } 453 | //} 454 | 455 | //func BenchmarkReadInts(b *testing.B) { 456 | // var ls Struct 457 | // bsr := &byteSliceReader{} 458 | // var r io.Reader = bsr 459 | // b.SetBytes(2 * (1 + 2 + 4 + 8)) 460 | // b.ResetTimer() 461 | // for i := 0; i < b.N; i++ { 462 | // bsr.remain = big 463 | // Read(r, BigEndian, &ls.Int8) 464 | // Read(r, BigEndian, &ls.Int16) 465 | // Read(r, BigEndian, &ls.Int32) 466 | // Read(r, BigEndian, &ls.Int64) 467 | // Read(r, BigEndian, &ls.Uint8) 468 | // Read(r, BigEndian, &ls.Uint16) 469 | // Read(r, BigEndian, &ls.Uint32) 470 | // Read(r, BigEndian, &ls.Uint64) 471 | // } 472 | // b.StopTimer() 473 | // want := s 474 | // want.Float32 = 0 475 | // want.Float64 = 0 476 | // want.Complex64 = 0 477 | // want.Complex128 = 0 478 | // want.Array = [4]uint8{0, 0, 0, 0} 479 | // want.Bool = false 480 | // want.BoolArray = [4]bool{false, false, false, false} 481 | // if b.N > 0 && !reflect.DeepEqual(ls, want) { 482 | // b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want) 483 | // } 484 | //} 485 | 486 | //func BenchmarkWriteInts(b *testing.B) { 487 | // buf := new(bytes.Buffer) 488 | // var w io.Writer = buf 489 | // b.SetBytes(2 * (1 + 2 + 4 + 8)) 490 | // b.ResetTimer() 491 | // for i := 0; i < b.N; i++ { 492 | // buf.Reset() 493 | // Write(w, BigEndian, s.Int8) 494 | // Write(w, BigEndian, s.Int16) 495 | // Write(w, BigEndian, s.Int32) 496 | // Write(w, BigEndian, s.Int64) 497 | // Write(w, BigEndian, s.Uint8) 498 | // Write(w, BigEndian, s.Uint16) 499 | // Write(w, BigEndian, s.Uint32) 500 | // Write(w, BigEndian, s.Uint64) 501 | // } 502 | // b.StopTimer() 503 | // if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) { 504 | // b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30]) 505 | // } 506 | //} 507 | 508 | //func BenchmarkWriteSlice1000Int32s(b *testing.B) { 509 | // slice := make([]int32, 1000) 510 | // buf := new(bytes.Buffer) 511 | // var w io.Writer = buf 512 | // b.SetBytes(4 * 1000) 513 | // b.ResetTimer() 514 | // for i := 0; i < b.N; i++ { 515 | // buf.Reset() 516 | // Write(w, BigEndian, slice) 517 | // } 518 | // b.StopTimer() 519 | //} 520 | -------------------------------------------------------------------------------- /coder.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | var ( 10 | // ErrNotEnoughSpace buffer not enough 11 | ErrNotEnoughSpace = errors.New("not enough space") 12 | ) 13 | 14 | type coder struct { 15 | buff []byte 16 | pos int 17 | 18 | boolPos int //index of last bool set in buff 19 | boolBit byte //bit of next aviable bool 20 | endian Endian 21 | } 22 | 23 | func (cder *coder) setEndian(endian Endian) { 24 | cder.endian = endian 25 | } 26 | 27 | // Buffer returns the byte slice that has been encoding/decoding. 28 | func (cder *coder) Buffer() []byte { 29 | return cder.buff[:cder.pos] 30 | } 31 | 32 | // Len returns unmber of bytes that has been encoding/decoding. 33 | func (cder *coder) Len() int { 34 | return cder.pos 35 | } 36 | 37 | // Cap returns number total bytes of cder coder buffer. 38 | func (cder *coder) Cap() int { 39 | return len(cder.buff) 40 | } 41 | 42 | // Skip ignore the next size of bytes for encoding/decoding and 43 | // set skiped bytes to 0. 44 | // It will panic if space not enough. 45 | // It will return -1 if size <= 0. 46 | func (cder *coder) Skip(size int) int { 47 | newPos := cder.pos + size 48 | if size >= 0 && newPos <= cder.Cap() { 49 | for i, b := size-1, cder.buff[cder.pos:newPos]; i >= 0; i-- { //zero skiped bytes 50 | b[i] = 0 51 | } 52 | cder.pos = newPos 53 | return size 54 | } 55 | return -1 56 | } 57 | 58 | // Reset move the read/write pointer to the beginning of buffer 59 | // and set all reseted bytes to 0. 60 | func (cder *coder) Reset() { 61 | for i := cder.pos - 1; i >= 0; i-- { //zero encoded bytes 62 | cder.buff[i] = 0 63 | } 64 | cder.pos = 0 65 | cder.resetBoolCoder() 66 | } 67 | 68 | // reset the state of bool coder 69 | func (cder *coder) resetBoolCoder() { 70 | cder.boolPos = -1 71 | cder.boolBit = 0 72 | } 73 | 74 | // reserve returns next size bytes for encoding/decoding. 75 | // it will panic if not enough space. 76 | func (cder *coder) reserve(size int) []byte { 77 | newPos := cder.pos + size 78 | if newPos > cder.Cap() { 79 | panic(fmt.Errorf("binary.Coder:buffer overflow pos=%d cap=%d require=%d, not enough space", cder.pos, cder.Cap(), size)) 80 | } 81 | if size > 0 && newPos <= cder.Cap() { 82 | b := cder.buff[cder.pos:newPos] 83 | cder.pos = newPos 84 | return b 85 | } 86 | return nil 87 | } 88 | 89 | // BytesReader transform bytes as Reader 90 | type BytesReader []byte 91 | 92 | // Read from bytes 93 | func (p *BytesReader) Read(data []byte) (n int, err error) { 94 | n = copy(data, *p) 95 | if n == len(*p) { 96 | err = io.EOF 97 | } 98 | *p = (*p)[n:] 99 | return 100 | } 101 | 102 | // BytesWriter transform bytes as Writer 103 | type BytesWriter []byte 104 | 105 | // Write to bytes 106 | func (p *BytesWriter) Write(data []byte) (n int, err error) { 107 | n = copy(*p, data) 108 | if n < len(data) { 109 | err = ErrNotEnoughSpace 110 | } 111 | *p = (*p)[n:] 112 | return 113 | } 114 | -------------------------------------------------------------------------------- /coder_test.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "reflect" 7 | "testing" 8 | "unsafe" 9 | ) 10 | 11 | type TDoNotSupport struct { 12 | DeepPointer **uint32 13 | Uintptr uintptr 14 | UnsafePointer unsafe.Pointer 15 | Ch chan bool 16 | Map map[uintptr]uintptr 17 | Map2 map[int]uintptr 18 | Map3 map[uintptr]int 19 | Slice []uintptr 20 | Array [2]uintptr 21 | Array2 [2][2]uintptr 22 | Array3 [2]struct{ A uintptr } 23 | Func func() 24 | Struct struct { 25 | Uintptr uintptr 26 | } 27 | Struct2 struct { 28 | PStruct *struct { 29 | PPUintptr **uintptr 30 | } 31 | } 32 | Struct3 struct { 33 | PStruct *struct { 34 | PUintptr *uintptr 35 | PPUintptr **uintptr 36 | } 37 | } 38 | PStruct *struct { 39 | PUintptr *uintptr 40 | PPUintptr **uintptr 41 | } 42 | } 43 | 44 | var doNotSupportTypes = TDoNotSupport{ 45 | Map2: map[int]uintptr{1: 1}, 46 | Map3: map[uintptr]int{2: 2}, 47 | } 48 | 49 | type fastValues struct { 50 | Int int 51 | Uint uint 52 | Bool bool 53 | Int8 int8 54 | Int16 int16 55 | Int32 int32 56 | Int64 int64 57 | Uint8 uint8 58 | Uint16 uint16 59 | Uint32 uint32 60 | Uint64 uint64 61 | Float32 float32 62 | Float64 float64 63 | Complex64 complex64 64 | Complex128 complex128 65 | String string 66 | IntSlice []int 67 | UintSlice []uint 68 | BoolSlice []bool 69 | Int8Slice []int8 70 | Int16Slice []int16 71 | Int32Slice []int32 72 | Int64Slice []int64 73 | Uint8Slice []uint8 74 | Uint16Slice []uint16 75 | Uint32Slice []uint32 76 | Uint64Slice []uint64 77 | Float32Slice []float32 78 | Float64Slice []float64 79 | Complex64Slice []complex64 80 | Complex128Slice []complex128 81 | StringSlice []string 82 | } 83 | 84 | var _fastValues = fastValues{ 85 | Int: -2, 86 | Uint: 2, 87 | Bool: true, 88 | Int8: -3, 89 | Int16: -4, 90 | Int32: -5, 91 | Int64: -6, 92 | Uint8: 3, 93 | Uint16: 4, 94 | Uint32: 5, 95 | Uint64: 6, 96 | Float32: -7, 97 | Float64: 7, 98 | Complex64: 8, 99 | Complex128: 9, 100 | String: "hello", 101 | IntSlice: []int{-1, 2}, 102 | UintSlice: []uint{1, 3}, 103 | BoolSlice: []bool{false, true}, 104 | Int8Slice: []int8{-1, 2}, 105 | Int16Slice: []int16{-1, 3}, 106 | Int32Slice: []int32{-1, 4}, 107 | Int64Slice: []int64{-1, 5}, 108 | Uint8Slice: []uint8{1, 6}, 109 | Uint16Slice: []uint16{1, 7}, 110 | Uint32Slice: []uint32{1, 8}, 111 | Uint64Slice: []uint64{1, 9}, 112 | Float32Slice: []float32{1, 10.1}, 113 | Float64Slice: []float64{1, 11.2}, 114 | Complex64Slice: []complex64{1, 2.2}, 115 | Complex128Slice: []complex128{1, 12.9}, 116 | StringSlice: []string{"abc", "bcd"}, 117 | } 118 | 119 | type baseStruct struct { 120 | Int8 int8 121 | Int16 int16 122 | Int32 int32 123 | Int64 int64 124 | Uint8 uint8 125 | Uint16 uint16 126 | Uint32 uint32 127 | Uint64 uint64 128 | Float32 float32 129 | Float64 float64 130 | Complex64 complex64 131 | Complex128 complex128 132 | Array [4]uint8 133 | Bool bool 134 | BoolArray [9]bool 135 | } 136 | 137 | type littleStruct struct { 138 | String string 139 | Int16 int16 140 | } 141 | 142 | type fullStruct struct { 143 | BaseStruct baseStruct 144 | LittleStruct littleStruct 145 | PLittleStruct *littleStruct 146 | String string 147 | PString *string 148 | PInt32 *int32 149 | Slice []*littleStruct 150 | PSlice *[]*string 151 | Float64Slice []float64 152 | BoolSlice []bool 153 | Uint32Slice []uint32 154 | Map map[string]*littleStruct 155 | Map2 map[string]uint16 156 | IntSlice []int 157 | UintSlice []uint 158 | } 159 | 160 | var full = fullStruct{ 161 | BaseStruct: baseStruct{ 162 | Int8: 0x12, 163 | Int16: 0x1234, 164 | Int32: 0x12345678, 165 | Int64: 0x123456789abcdef0, 166 | Uint8: 0x12, 167 | Uint16: 0x1234, 168 | Uint32: 0x71234568, 169 | Uint64: 0xa123456789bcdef0, 170 | Float32: 1234.5678, 171 | Float64: 2345.6789012, 172 | Complex64: complex(1.12456453, 2.344565), 173 | Complex128: complex(333.4569789789123, 567.34577890012), 174 | Array: [4]uint8{0x1, 0x2, 0x3, 0x4}, 175 | Bool: false, 176 | BoolArray: [9]bool{true, false, false, false, false, true, true, false, true}, 177 | }, 178 | LittleStruct: littleStruct{ 179 | String: "abc", 180 | Int16: 0x1234, 181 | }, 182 | PLittleStruct: &littleStruct{ 183 | String: "bcd", 184 | Int16: 0x2345, 185 | }, 186 | String: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 187 | PString: newString("hello"), 188 | PInt32: newInt32(0x11223344), 189 | Slice: []*littleStruct{ 190 | &littleStruct{ 191 | String: "abc", 192 | Int16: 0x1122, 193 | }, 194 | &littleStruct{ 195 | String: "bcd", 196 | Int16: 0x2233, 197 | }, 198 | &littleStruct{ 199 | String: "cdef", 200 | Int16: 0x3344, 201 | }, 202 | }, 203 | PSlice: &[]*string{newString("abc"), newString("def"), newString("ghijkl")}, 204 | Float64Slice: []float64{3.141592654, 1.137856998, 6.789012345}, 205 | BoolSlice: []bool{false, true, false, false, true, true, false}, 206 | Uint32Slice: []uint32{0x12345678, 0x23456789, 0x34567890, 0x4567890a, 0x567890ab}, 207 | Map: map[string]*littleStruct{"a": &littleStruct{String: "a", Int16: 0x1122}, "b": &littleStruct{String: "b", Int16: 0x1122}}, 208 | Map2: map[string]uint16{"aaa": 0x5566, "bbb": 0x7788}, 209 | IntSlice: []int{0, -1, 1, -2, 2, -63, 63, -64, 64, -65, 65, -125, 125, -126, 126, -127, 127, -128, 128, -32765, 32765, -32766, 32766, -32767, 32767, -32768, 32768, -2147483645, 2147483645, -2147483646, 2147483646, -2147483647, 2147483647, -2147483648, 2147483648, -9223372036854775807, 9223372036854775806, -9223372036854775808, 9223372036854775807}, 210 | UintSlice: []uint{0, 1, 2, 127, 128, 32765, 32766, 32767, 32768, 65533, 65534, 65535, 65536, 0xFFFFFD, 0xFFFFFE, 0xFFFFFF, 0xFFFFFFFFFFFFFFFD, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF}, 211 | } 212 | 213 | func newString(s string) *string { 214 | p := new(string) 215 | *p = s 216 | return p 217 | } 218 | func newInt32(i int32) *int32 { 219 | p := new(int32) 220 | *p = i 221 | return p 222 | } 223 | 224 | var bigFull = []byte{ 225 | //field#1|BaseStruct|binary.baseStruct{Int8:18, Int16:4660, Int32:305419896, Int64:1311768467463790320, Uint8:0x12, Uint16:0x1234, Uint32:0x71234568, Uint64:0xa123456789bcdef0, Float32:1234.5677, Float64:2345.6789012, Complex64:(1.1245645+2.344565i), Complex128:(333.4569789789123+567.34577890012i), Array:[4]uint8{0x1, 0x2, 0x3, 0x4}, Bool:false, BoolArray:[9]bool{true, false, false, false, false, true, true, false, true}} 226 | 0x12, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x12, 0x34, 0x71, 0x23, 0x45, 0x68, 0xa1, 0x23, 0x45, 0x67, 0x89, 0xbc, 0xde, 0xf0, 0x44, 0x9a, 0x52, 0x2b, 0x40, 0xa2, 0x53, 0x5b, 0x98, 0xf0, 0x26, 0x6e, 0x3f, 0x8f, 0xf1, 0xbb, 0x40, 0x16, 0x0d, 0x5a, 0x40, 0x74, 0xd7, 0x4f, 0xc9, 0x30, 0x96, 0x34, 0x40, 0x81, 0xba, 0xc4, 0x27, 0xba, 0x5d, 0x4c, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x09, 0x61, 0x01, 227 | //field#2|LittleStruct|binary.littleStruct{String:"abc", Int16:4660} 228 | 0x03, 0x61, 0x62, 0x63, 0x12, 0x34, 229 | //field#3|PLittleStruct|&binary.littleStruct{String:"bcd", Int16:9029} 230 | 0x03, 0x62, 0x63, 0x64, 0x23, 0x45, 231 | //field#4|String|"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 232 | 0x40, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 233 | //field#5|PString|(*string)(0xc042033170) 234 | 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 235 | //field#6|PInt32|(*int32)(0xc04200e268) 236 | 0x11, 0x22, 0x33, 0x44, 237 | //field#7|Slice|[]*binary.littleStruct{(*binary.littleStruct)(0x68f620), (*binary.littleStruct)(0x68f640), (*binary.littleStruct)(0x68f660)} 238 | 0x03, 0x07, 0x03, 0x61, 0x62, 0x63, 0x11, 0x22, 0x03, 0x62, 0x63, 0x64, 0x22, 0x33, 0x04, 0x63, 0x64, 0x65, 0x66, 0x33, 0x44, 239 | //field#8|PSlice|&[]*string{(*string)(0xc042033180), (*string)(0xc042033190), (*string)(0xc0420331a0)} 240 | 0x03, 0x07, 0x03, 0x61, 0x62, 0x63, 0x03, 0x64, 0x65, 0x66, 0x06, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 241 | //field#9|Float64Slice|[]float64{3.141592654, 1.137856998, 6.789012345} 242 | 0x03, 0x40, 0x09, 0x21, 0xfb, 0x54, 0x52, 0x45, 0x50, 0x3f, 0xf2, 0x34, 0xa9, 0x8a, 0x1e, 0xf4, 0xaf, 0x40, 0x1b, 0x27, 0xf2, 0xda, 0x27, 0xa9, 0x3c, 243 | //field#10|BoolSlice|[]bool{false, true, false, false, true, true, false} 244 | 0x07, 0x32, 245 | //field#11|Uint32Slice|[]uint32{0x12345678, 0x23456789, 0x34567890, 0x4567890a, 0x567890ab} 246 | 0x05, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x90, 0x45, 0x67, 0x89, 0x0a, 0x56, 0x78, 0x90, 0xab, 247 | //field#12|Map|map[string]*binary.littleStruct{"a":(*binary.littleStruct)(0xc0420029c0), "b":(*binary.littleStruct)(0xc0420029e0)} 248 | 0x02, 0x01, 0x61, 0x03, 0x01, 0x61, 0x11, 0x22, 0x01, 0x62, 0x01, 0x62, 0x11, 0x22, 249 | //field#13|Map2|map[string]uint16{"aaa":0x5566, "bbb":0x7788} 250 | 0x02, 0x03, 0x61, 0x61, 0x61, 0x55, 0x66, 0x03, 0x62, 0x62, 0x62, 0x77, 0x88, 251 | //field#14|IntSlice|[]int{0, -1, 1, -2, 2, -63, 63, -64, 64, -65, 65, -125, 125, -126, 126, -127, 127, -128, 128, -32765, 32765, -32766, 32766, -32767, 32767, -32768, 32768, -2147483645, 2147483645, -2147483646, 2147483646, -2147483647, 2147483647, -2147483648, 2147483648, -9223372036854775807, 9223372036854775806, -9223372036854775808, 9223372036854775807} 252 | 0x27, 0x00, 0x01, 0x02, 0x03, 0x04, 0x7d, 0x7e, 0x7f, 0x80, 0x01, 0x81, 0x01, 0x82, 0x01, 0xf9, 0x01, 0xfa, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfd, 0x01, 0xfe, 0x01, 0xff, 0x01, 0x80, 0x02, 0xf9, 0xff, 0x03, 0xfa, 0xff, 0x03, 0xfb, 0xff, 0x03, 0xfc, 0xff, 0x03, 0xfd, 0xff, 0x03, 0xfe, 0xff, 0x03, 0xff, 0xff, 0x03, 0x80, 0x80, 0x04, 0xf9, 0xff, 0xff, 0xff, 0x0f, 0xfa, 0xff, 0xff, 0xff, 0x0f, 0xfb, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0xff, 0x0f, 0xfd, 0xff, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 253 | //field#15|UintSlice|[]uint{0x0, 0x1, 0x2, 0x7f, 0x80, 0x7ffd, 0x7ffe, 0x7fff, 0x8000, 0xfffd, 0xfffe, 0xffff, 0x10000, 0xfffffd, 0xfffffe, 0xffffff, 0xfffffffffffffffd, 0xfffffffffffffffe, 0xffffffffffffffff} 254 | 0x13, 0x00, 0x01, 0x02, 0x7f, 0x80, 0x01, 0xfd, 0xff, 0x01, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x01, 0x80, 0x80, 0x02, 0xfd, 0xff, 0x03, 0xfe, 0xff, 0x03, 0xff, 0xff, 0x03, 0x80, 0x80, 0x04, 0xfd, 0xff, 0xff, 0x07, 0xfe, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 255 | } 256 | 257 | var littleFull = []byte{ 258 | //field#1|BaseStruct|binary.baseStruct{Int8:18, Int16:4660, Int32:305419896, Int64:1311768467463790320, Uint8:0x12, Uint16:0x1234, Uint32:0x71234568, Uint64:0xa123456789bcdef0, Float32:1234.5677, Float64:2345.6789012, Complex64:(1.1245645+2.344565i), Complex128:(333.4569789789123+567.34577890012i), Array:[4]uint8{0x1, 0x2, 0x3, 0x4}, Bool:false, BoolArray:[9]bool{true, false, false, false, false, true, true, false, true}} 259 | 0x12, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x12, 0x34, 0x12, 0x68, 0x45, 0x23, 0x71, 0xf0, 0xde, 0xbc, 0x89, 0x67, 0x45, 0x23, 0xa1, 0x2b, 0x52, 0x9a, 0x44, 0x6e, 0x26, 0xf0, 0x98, 0x5b, 0x53, 0xa2, 0x40, 0xbb, 0xf1, 0x8f, 0x3f, 0x5a, 0x0d, 0x16, 0x40, 0x34, 0x96, 0x30, 0xc9, 0x4f, 0xd7, 0x74, 0x40, 0x4c, 0x5d, 0xba, 0x27, 0xc4, 0xba, 0x81, 0x40, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x09, 0x61, 0x01, 260 | //field#2|LittleStruct|binary.littleStruct{String:"abc", Int16:4660} 261 | 0x03, 0x61, 0x62, 0x63, 0x34, 0x12, 262 | //field#3|PLittleStruct|&binary.littleStruct{String:"bcd", Int16:9029} 263 | 0x03, 0x62, 0x63, 0x64, 0x45, 0x23, 264 | //field#4|String|"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 265 | 0x40, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 266 | //field#5|PString|(*string)(0xc042033170) 267 | 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 268 | //field#6|PInt32|(*int32)(0xc04200e268) 269 | 0x44, 0x33, 0x22, 0x11, 270 | //field#7|Slice|[]*binary.littleStruct{(*binary.littleStruct)(0x68f400), (*binary.littleStruct)(0x68f420), (*binary.littleStruct)(0x68f440)} 271 | 0x03, 0x07, 0x03, 0x61, 0x62, 0x63, 0x22, 0x11, 0x03, 0x62, 0x63, 0x64, 0x33, 0x22, 0x04, 0x63, 0x64, 0x65, 0x66, 0x44, 0x33, 272 | //field#8|PSlice|&[]*string{(*string)(0xc042033180), (*string)(0xc042033190), (*string)(0xc0420331a0)} 273 | 0x03, 0x07, 0x03, 0x61, 0x62, 0x63, 0x03, 0x64, 0x65, 0x66, 0x06, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 274 | //field#9|Float64Slice|[]float64{3.141592654, 1.137856998, 6.789012345} 275 | 0x03, 0x50, 0x45, 0x52, 0x54, 0xfb, 0x21, 0x09, 0x40, 0xaf, 0xf4, 0x1e, 0x8a, 0xa9, 0x34, 0xf2, 0x3f, 0x3c, 0xa9, 0x27, 0xda, 0xf2, 0x27, 0x1b, 0x40, 276 | //field#10|BoolSlice|[]bool{false, true, false, false, true, true, false} 277 | 0x07, 0x32, 278 | //field#11|Uint32Slice|[]uint32{0x12345678, 0x23456789, 0x34567890, 0x4567890a, 0x567890ab} 279 | 0x05, 0x78, 0x56, 0x34, 0x12, 0x89, 0x67, 0x45, 0x23, 0x90, 0x78, 0x56, 0x34, 0x0a, 0x89, 0x67, 0x45, 0xab, 0x90, 0x78, 0x56, 280 | //field#12|Map|map[string]*binary.littleStruct{"b":(*binary.littleStruct)(0xc0420029e0), "a":(*binary.littleStruct)(0xc0420029c0)} 281 | 0x02, 0x01, 0x61, 0x03, 0x01, 0x61, 0x22, 0x11, 0x01, 0x62, 0x01, 0x62, 0x22, 0x11, 282 | //field#13|Map2|map[string]uint16{"aaa":0x5566, "bbb":0x7788} 283 | 0x02, 0x03, 0x61, 0x61, 0x61, 0x66, 0x55, 0x03, 0x62, 0x62, 0x62, 0x88, 0x77, 284 | //field#14|IntSlice|[]int{0, -1, 1, -2, 2, -63, 63, -64, 64, -65, 65, -125, 125, -126, 126, -127, 127, -128, 128, -32765, 32765, -32766, 32766, -32767, 32767, -32768, 32768, -2147483645, 2147483645, -2147483646, 2147483646, -2147483647, 2147483647, -2147483648, 2147483648, -9223372036854775807, 9223372036854775806, -9223372036854775808, 9223372036854775807} 285 | 0x27, 0x00, 0x01, 0x02, 0x03, 0x04, 0x7d, 0x7e, 0x7f, 0x80, 0x01, 0x81, 0x01, 0x82, 0x01, 0xf9, 0x01, 0xfa, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfd, 0x01, 0xfe, 0x01, 0xff, 0x01, 0x80, 0x02, 0xf9, 0xff, 0x03, 0xfa, 0xff, 0x03, 0xfb, 0xff, 0x03, 0xfc, 0xff, 0x03, 0xfd, 0xff, 0x03, 0xfe, 0xff, 0x03, 0xff, 0xff, 0x03, 0x80, 0x80, 0x04, 0xf9, 0xff, 0xff, 0xff, 0x0f, 0xfa, 0xff, 0xff, 0xff, 0x0f, 0xfb, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0xff, 0x0f, 0xfd, 0xff, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 286 | //field#15|UintSlice|[]uint{0x0, 0x1, 0x2, 0x7f, 0x80, 0x7ffd, 0x7ffe, 0x7fff, 0x8000, 0xfffd, 0xfffe, 0xffff, 0x10000, 0xfffffd, 0xfffffe, 0xffffff, 0xfffffffffffffffd, 0xfffffffffffffffe, 0xffffffffffffffff} 287 | 0x13, 0x00, 0x01, 0x02, 0x7f, 0x80, 0x01, 0xfd, 0xff, 0x01, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x01, 0x80, 0x80, 0x02, 0xfd, 0xff, 0x03, 0xfe, 0xff, 0x03, 0xff, 0xff, 0x03, 0x80, 0x80, 0x04, 0xfd, 0xff, 0xff, 0x07, 0xfe, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 288 | } 289 | 290 | var littleFullAll = []byte{ 291 | 0x12, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 292 | 0x34, 0x12, 0x12, 0x34, 0x12, 0x68, 0x45, 0x23, 0x71, 0xf0, 0xde, 0xbc, 0x89, 293 | 0x67, 0x45, 0x23, 0xa1, 0x2b, 0x52, 0x9a, 0x44, 0x6e, 0x26, 0xf0, 0x98, 0x5b, 294 | 0x53, 0xa2, 0x40, 0xbb, 0xf1, 0x8f, 0x3f, 0x5a, 0x0d, 0x16, 0x40, 0x34, 0x96, 295 | 0x30, 0xc9, 0x4f, 0xd7, 0x74, 0x40, 0x4c, 0x5d, 0xba, 0x27, 0xc4, 0xba, 0x81, 296 | 0x40, 0x04, 0x01, 0x02, 0x03, 0x04, 0xfe, 0x09, 0x61, 0x01, 0x03, 0x61, 0x62, 297 | 0x63, 0x34, 0x12, 0x03, 0x62, 0x63, 0x64, 0x45, 0x23, 0x40, 0x30, 0x31, 0x32, 298 | 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 299 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 300 | 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 301 | 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 302 | 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x05, 0x68, 0x65, 0x6c, 303 | 0x6c, 0x6f, 0x44, 0x33, 0x22, 0x11, 0x03, 0x03, 0x61, 0x62, 0x63, 0x22, 0x11, 304 | 0x03, 0x62, 0x63, 0x64, 0x33, 0x22, 0x04, 0x63, 0x64, 0x65, 0x66, 0x44, 0x33, 305 | 0x03, 0x1f, 0x03, 0x61, 0x62, 0x63, 0x03, 0x64, 0x65, 0x66, 0x06, 0x67, 0x68, 306 | 0x69, 0x6a, 0x6b, 0x6c, 0x03, 0x50, 0x45, 0x52, 0x54, 0xfb, 0x21, 0x09, 0x40, 307 | 0xaf, 0xf4, 0x1e, 0x8a, 0xa9, 0x34, 0xf2, 0x3f, 0x3c, 0xa9, 0x27, 0xda, 0xf2, 308 | 0x27, 0x1b, 0x40, 0x07, 0x32, 0x05, 0x78, 0x56, 0x34, 0x12, 0x89, 0x67, 0x45, 309 | 0x23, 0x90, 0x78, 0x56, 0x34, 0x0a, 0x89, 0x67, 0x45, 0xab, 0x90, 0x78, 0x56, 310 | 0x02, 0x01, 0x61, 0x01, 0x61, 0x22, 0x11, 0x01, 0x62, 0x01, 0x62, 0x22, 0x11, 311 | 0x02, 0x03, 0x61, 0x61, 0x61, 0x66, 0x55, 0x03, 0x62, 0x62, 0x62, 0x88, 0x77, 312 | 0x27, 0x00, 0x01, 0x02, 0x03, 0x04, 0x7d, 0x7e, 0x7f, 0x80, 0x01, 0x81, 0x01, 313 | 0x82, 0x01, 0xf9, 0x01, 0xfa, 0x01, 0xfb, 0x01, 0xfc, 0x01, 0xfd, 0x01, 0xfe, 314 | 0x01, 0xff, 0x01, 0x80, 0x02, 0xf9, 0xff, 0x03, 0xfa, 0xff, 0x03, 0xfb, 0xff, 315 | 0x03, 0xfc, 0xff, 0x03, 0xfd, 0xff, 0x03, 0xfe, 0xff, 0x03, 0xff, 0xff, 0x03, 316 | 0x80, 0x80, 0x04, 0xf9, 0xff, 0xff, 0xff, 0x0f, 0xfa, 0xff, 0xff, 0xff, 0x0f, 317 | 0xfb, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0xff, 0x0f, 0xfd, 0xff, 0xff, 318 | 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 319 | 0x80, 0x80, 0x80, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 320 | 0x01, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 321 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 322 | 0xff, 0xff, 0xff, 0xff, 0x01, 0x13, 0x00, 0x01, 0x02, 0x7f, 0x80, 0x01, 0xfd, 323 | 0xff, 0x01, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x01, 0x80, 0x80, 0x02, 0xfd, 0xff, 324 | 0x03, 0xfe, 0xff, 0x03, 0xff, 0xff, 0x03, 0x80, 0x80, 0x04, 0xfd, 0xff, 0xff, 325 | 0x07, 0xfe, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0xff, 326 | 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 327 | 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 328 | } 329 | 330 | func TestEncode(t *testing.T) { 331 | v := reflect.ValueOf(full) 332 | vt := v.Type() 333 | n := v.NumField() 334 | check := littleFull 335 | for i := 0; i < n; i++ { 336 | if !validField(vt.Field(i)) { 337 | continue 338 | } 339 | b, err := Encode(v.Field(i).Interface(), nil) 340 | c := check[:len(b)] 341 | check = check[len(b):] 342 | if err != nil { 343 | t.Error(err) 344 | } 345 | //fmt.Printf("//field#%d|%s|%#v\n$% x,\n", i+1, vt.Field(i).Name, v.Field(i).Interface(), b) 346 | if vt.Field(i).Type.Kind() != reflect.Map && //map keys will be got as unspecified order, byte order may change but it doesn't matter 347 | !reflect.DeepEqual(b, c) { 348 | //fmt.Printf("%d %s\ngot%#v\n%need#v\n", i, vt.Field(i).Type.String(), b, c) 349 | t.Errorf("field %d %s got %+v\nneed %+v\n", i, vt.Field(i).Name, b, c) 350 | } 351 | } 352 | 353 | ////map fields will case uncertain bytes order but it does't matter 354 | //b2, err := Encode(full, nil) 355 | //if err != nil { 356 | // t.Error(err) 357 | //} 358 | //fmt.Printf("//% x,\n", b2) 359 | //if !reflect.DeepEqual(b2, littleFull) { 360 | // t.Errorf("got %+v\nneed %+v\n", b2, littleFull) 361 | //} 362 | } 363 | 364 | func TestEncodeBig(t *testing.T) { 365 | v := reflect.ValueOf(full) 366 | vt := v.Type() 367 | n := v.NumField() 368 | check := bigFull 369 | for i := 0; i < n; i++ { 370 | if !validField(vt.Field(i)) { 371 | continue 372 | } 373 | size := Sizeof(v.Field(i).Interface()) 374 | encoder := NewEncoderEndian(size, BigEndian) 375 | err := encoder.Value(v.Field(i).Interface()) 376 | b := encoder.Buffer() 377 | c := check[:len(b)] 378 | check = check[len(b):] 379 | if err != nil { 380 | t.Error(err) 381 | } 382 | //fmt.Printf("//field#%d|%s|%#v\n$% x,\n", i+1, vt.Field(i).Name, v.Field(i).Interface(), b) 383 | if vt.Field(i).Type.Kind() != reflect.Map && //map keys will be got as unspecified order, byte order may change but it doesn't matter 384 | !reflect.DeepEqual(b, c) { 385 | //fmt.Printf("%d %s\ngot%#v\n%need#v\n", i, vt.Field(i).Type.String(), b, c) 386 | t.Errorf("field %d %s got %+v\nneed %+v\n", i, vt.Field(i).Name, b, c) 387 | } 388 | } 389 | } 390 | 391 | func TestDecode(t *testing.T) { 392 | var v fullStruct 393 | err := Decode(littleFullAll, &v) 394 | if err != nil { 395 | t.Error(err) 396 | } 397 | if !reflect.DeepEqual(v, full) { 398 | t.Errorf("got %#v\nneed %#v\n", v, full) 399 | } 400 | } 401 | 402 | func TestReset(t *testing.T) { 403 | encoder := NewEncoder(100) 404 | encoder.Uint64(0x1122334455667788, false) 405 | encoder.String("0123456789abcdef") 406 | oldCheck := []byte{0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x10, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66} 407 | old := encoder.Buffer() 408 | l := encoder.Len() 409 | if len(old) != l { 410 | t.Errorf("encode len error: got %#v\nneed %#v\n", old, l) 411 | } 412 | 413 | if !reflect.DeepEqual(old, oldCheck) { 414 | t.Errorf("got %#v\nneed %#v\n", old, oldCheck) 415 | } 416 | encoder.Reset() 417 | var s struct { 418 | PString *string 419 | PSlice *[]int 420 | PArray *[2]bool 421 | PArray2 *[2]struct{ X *string } 422 | PInt *int32 423 | PStruct *struct{ A int } 424 | PStruct2 *struct{ B *[]string } 425 | } 426 | err := encoder.Value(&s) 427 | if err != nil { 428 | t.Error(err) 429 | } 430 | _new := encoder.Buffer() 431 | l2 := encoder.Len() 432 | newCheck := []byte{0x0} 433 | if len(_new) != l2 { 434 | t.Errorf("encode len error: got %#v\nneed %#v\n", _new, l2) 435 | } 436 | if !reflect.DeepEqual(_new, newCheck) { 437 | t.Errorf("got %#v\nneed %#v\n", _new, newCheck) 438 | } 439 | if s := encoder.Skip(1); s < 0 { 440 | t.Errorf("got %#v\nneed %#v\n", s, 1) 441 | } 442 | if s := encoder.Skip(encoder.Cap()); s >= 0 { 443 | t.Errorf("got %#v\nneed %#v\n", s, -1) 444 | } 445 | r := encoder.reserve(0) 446 | if r != nil { 447 | t.Errorf("got %#v\nneed %#v\n", r, nil) 448 | } 449 | 450 | defer func() { 451 | if e := recover(); e == nil { 452 | t.Error("need panic but not") 453 | } 454 | }() 455 | 456 | if !encoder.ResizeBuffer(101) { 457 | t.Errorf("Decoder: have %v, want %v", false, true) 458 | } 459 | 460 | large := [100]complex128{} 461 | err2 := encoder.Value(&large) 462 | if err2 == nil { 463 | t.Errorf("got err=nil, need err=none-nil") 464 | } else { 465 | //println("info******", err2.Error()) 466 | } 467 | 468 | r2 := encoder.reserve(100) 469 | if r2 != nil { 470 | t.Errorf("got %#v\nneed %#v\n", r2, nil) 471 | } 472 | } 473 | 474 | func TestEncodeEmptyPointer(t *testing.T) { 475 | var s struct { 476 | PString *string 477 | PSlice *[]int 478 | PArray *[2]bool 479 | PArray2 *[2]struct{ X *string } 480 | PInt *int32 481 | PStruct *struct{ A int } 482 | PStruct2 *struct{ B *[]string } 483 | } 484 | b, err := Encode(&s, nil) 485 | if err != nil { 486 | t.Error(err) 487 | } 488 | ss := s 489 | 490 | err = Decode(b, &ss) 491 | if err != nil { 492 | t.Error(err) 493 | } 494 | 495 | b2, err2 := Encode(&ss, nil) 496 | if err2 != nil { 497 | t.Error(err) 498 | } 499 | if !reflect.DeepEqual(b, b2) { 500 | t.Errorf("%+v->%+v got %+v\nneed %+v\n", s, ss, b2, b) 501 | } 502 | check := []byte{0x0} 503 | if !reflect.DeepEqual(b2, check) { 504 | t.Errorf("got %+v\nneed %+v\n", b2, check) 505 | } 506 | } 507 | 508 | func TestHideStructField(t *testing.T) { 509 | type T struct { 510 | A uint32 511 | b uint32 512 | _ uint32 513 | C uint32 `binary:"ignore"` 514 | } 515 | var s T 516 | s.A = 0x11223344 517 | s.b = 0x22334455 518 | s.C = 0x33445566 519 | check := []byte{0x44, 0x33, 0x22, 0x11} 520 | b, err := Encode(s, nil) 521 | if err != nil { 522 | t.Error(err) 523 | } 524 | if !reflect.DeepEqual(b, check) { 525 | t.Errorf("%T: got %x; want %x", s, b, check) 526 | } 527 | var ss, ssCheck T 528 | ssCheck.A = s.A 529 | err = Decode(b, &ss) 530 | if err != nil { 531 | t.Error(err) 532 | } 533 | if !reflect.DeepEqual(ss, ssCheck) { 534 | t.Errorf("%T: got %q; want %q", s, ss, ssCheck) 535 | } 536 | } 537 | 538 | func TestEndian(t *testing.T) { 539 | if LittleEndian.String() != "LittleEndian" || 540 | LittleEndian.GoString() != "binary.LittleEndian" { 541 | t.Error("LittleEndian") 542 | } 543 | if BigEndian.String() != "BigEndian" || 544 | BigEndian.GoString() != "binary.BigEndian" { 545 | t.Error("BigEndian") 546 | } 547 | } 548 | 549 | func TestByteReaderWriter(t *testing.T) { 550 | buff := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 551 | reader := BytesReader(buff[:]) 552 | r := make([]byte, len(buff)-1) 553 | n, err := reader.Read(r) 554 | if err != nil { 555 | t.Error(err) 556 | } 557 | if n != len(r) { 558 | t.Errorf("got %+v\nneed %+v\n", n, len(r)) 559 | } 560 | if check := buff[:len(r)]; !reflect.DeepEqual(r, check) { 561 | t.Errorf("got %+v\nneed %+v\n", r, check) 562 | } 563 | n2, err2 := reader.Read(r) 564 | if n2 != 1 || err2 == nil { 565 | t.Errorf("got %d %+v\nneed %d %+v\n", n2, err2, 1, io.EOF) 566 | } 567 | 568 | wBuff := make([]byte, len(buff)+1) 569 | writer := BytesWriter(wBuff) 570 | w := buff[:] 571 | n3, err3 := writer.Write(w) 572 | if err3 != nil { 573 | t.Error(err3) 574 | } 575 | if n3 != len(w) { 576 | t.Errorf("got %+v\nneed %+v\n", n3, len(w)) 577 | } 578 | n4, err4 := writer.Write(w) 579 | if n4 != 1 || err4 == nil { 580 | t.Errorf("got %d %+v\nneed %d %+v\n", n4, err4, 1, ErrNotEnoughSpace) 581 | } 582 | wCheck := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0} 583 | if c := wBuff; !reflect.DeepEqual(c, wCheck) { 584 | t.Errorf("got %+v\nneed %+v\n", c, wCheck) 585 | } 586 | } 587 | 588 | func TestDecoderSkip(t *testing.T) { 589 | type skipedStruct struct { 590 | S string 591 | I int 592 | U uint 593 | Map map[uint32]uint32 594 | BoolArray [5]bool 595 | U16Array [5]uint16 596 | StrArray [5]string 597 | Struct struct{ A uint8 } 598 | Bool1 bool 599 | Pointer *uint32 600 | Bool2 bool 601 | Packed1 uint32 `binary:"packed"` 602 | Packed2 int64 `binary:"packed"` 603 | } 604 | RegStruct((*skipedStruct)(nil)) 605 | 606 | var w [5]skipedStruct 607 | for i := len(w) - 1; i >= 0; i-- { 608 | w[i].S = fmt.Sprintf("%d", i) 609 | w[i].I = i 610 | w[i].U = uint(i) 611 | w[i].Map = map[uint32]uint32{uint32(i): uint32(i), uint32(i + 1): uint32(i + 1)} 612 | w[i].Struct.A = uint8(i) 613 | w[i].U16Array[i] = uint16(i) 614 | w[i].BoolArray[i] = true 615 | w[i].Bool2 = true 616 | w[i].Packed1 = uint32(i) 617 | w[i].Packed2 = int64(i * 2) 618 | if i%2 == 0 { 619 | w[i].Pointer = new(uint32) 620 | } 621 | } 622 | 623 | var r [3]skipedStruct 624 | b, err := Encode(&w, nil) 625 | if err != nil { 626 | t.Error(err) 627 | } 628 | 629 | err2 := Decode(b, &r) 630 | if err2 != nil { 631 | t.Error(err2) 632 | } 633 | for i := len(r) - 1; i >= 0; i-- { 634 | if !reflect.DeepEqual(w[i], r[i]) { 635 | t.Errorf("%d got %+v\nneed %+v\n", i, w[i], r[i]) 636 | } 637 | } 638 | } 639 | 640 | //func TestDecoderSkipError(t *testing.T) { 641 | // // defer func() { 642 | // // if msg := recover(); msg == nil { 643 | // // t.Fatal("did not panic") 644 | // // } else { 645 | // // fmt.Println(msg) 646 | // // } 647 | // // }() 648 | 649 | // bytes := []byte{2, 0, 0, 0, 0} 650 | // var dataDecode [0]uintptr 651 | // decoder := NewDecoder(bytes) 652 | // n := decoder.skipByType(reflect.TypeOf(dataDecode), false) 653 | // if n >= 0 { 654 | // t.Errorf("DecoderSkipError: have %d, want %d", n, -1) 655 | // } else { 656 | // //println(n) 657 | // } 658 | //} 659 | 660 | func TestFastValue(t *testing.T) { 661 | s := _fastValues 662 | v := reflect.ValueOf(s) 663 | encoder := NewEncoder(Size(s)) 664 | for i := v.NumField() - 1; i >= 0; i-- { 665 | f := v.Field(i) 666 | if err := encoder.Value(f.Interface()); err != nil { 667 | t.Error(err) 668 | } 669 | } 670 | buffer := encoder.Buffer() 671 | 672 | var r fastValues 673 | vr := reflect.ValueOf(&r) 674 | vr = reflect.Indirect(vr) 675 | decoder := NewDecoder(buffer) 676 | for i := vr.NumField() - 1; i >= 0; i-- { 677 | f := vr.Field(i).Addr() 678 | oldSize := decoder.Len() 679 | if err := decoder.Value(f.Interface()); err != nil { 680 | t.Error(err) 681 | } 682 | size := decoder.Len() - oldSize 683 | assert(size == Sizeof(f.Interface()), "") 684 | } 685 | if !reflect.DeepEqual(r, s) { 686 | t.Errorf("got %+v\nneed %+v\n", r, s) 687 | } 688 | } 689 | 690 | func TestEncodeDonotSupportedType(t *testing.T) { 691 | ts := doNotSupportTypes 692 | if _, err := Encode(ts, nil); err == nil { 693 | t.Errorf("EncodeDonotSupportedType: have err == nil, want non-nil") 694 | } 695 | 696 | buff := make([]byte, 0) 697 | ecoder := NewEncoder(100) 698 | decoder := NewDecoder(buff) 699 | 700 | tv := reflect.Indirect(reflect.ValueOf(&ts)) 701 | for i, n := 0, tv.NumField(); i < n; i++ { 702 | if _, err := Encode(tv.Field(i).Interface(), nil); err == nil { 703 | t.Errorf("EncodeDonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) 704 | } else { 705 | //fmt.Println(err) 706 | } 707 | 708 | if err := ecoder.Value(tv.Field(i).Interface()); err == nil { 709 | t.Errorf("EncodeDonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) 710 | } else { 711 | //fmt.Println(err) 712 | } 713 | 714 | if err := Decode(buff, tv.Field(i).Addr().Interface()); err == nil { 715 | t.Errorf("Decode DonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) 716 | } else { 717 | //fmt.Printf("Decode error: %#v\n%s\n", tv.Field(i).Addr().Type().String(), err.Error()) 718 | } 719 | 720 | if err := decoder.value(tv.Field(i), true, false); err == nil { 721 | t.Errorf("EncodeDonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) 722 | } else { 723 | //fmt.Println(err) 724 | } 725 | } 726 | 727 | if queryStruct(tv.Type()).decode(decoder, tv) == nil { 728 | t.Errorf("decode DonotSupportedType.%v: have err == nil, want non-nil", tv.Type()) 729 | } 730 | } 731 | 732 | func TestDecoder(t *testing.T) { 733 | buffer := []byte{} 734 | decoder := NewDecoder(buffer) 735 | got := decoder.Skip(0) 736 | if got != -1 { 737 | t.Errorf("Decoder: have %d, want %d", got, -1) 738 | } 739 | n := decoder.skipByType(reflect.TypeOf(uintptr(0)), false) 740 | if n != -1 { 741 | t.Errorf("Decoder: have %d, want %d", n, -1) 742 | } 743 | } 744 | 745 | func TestAssert(t *testing.T) { 746 | defer func() { 747 | if msg := recover(); msg == nil { 748 | t.Fatal("did not panic") 749 | } 750 | }() 751 | 752 | message := "it will panic" 753 | assert(false, message) 754 | } 755 | 756 | func TestRegStruct(t *testing.T) { 757 | type StructForReg struct { 758 | A int 759 | B uint `binary:"ignore"` 760 | C int `binary:"int32"` 761 | d string 762 | _ int32 763 | F float32 764 | S struct { 765 | A int 766 | B string 767 | } 768 | S2 struct { 769 | A int 770 | B string 771 | } 772 | PS *struct { 773 | A int32 774 | B string 775 | } 776 | } 777 | RegStruct((*StructForReg)(nil)) 778 | if err := RegStruct((*StructForReg)(nil)); err == nil { //duplicate regist 779 | t.Errorf("RegStruct: have err == nil, want non-nil") 780 | } 781 | var a = StructForReg{ 782 | A: -5, 783 | B: 6, 784 | C: 7, 785 | d: "hello", 786 | F: 3.14, 787 | } 788 | a.S.A = 9 789 | a.S.B = "abc" 790 | b, err := Encode(&a, nil) 791 | if err != nil { 792 | t.Error(err) 793 | } 794 | 795 | var r StructForReg 796 | //fmt.Printf("%#v\n%#v\n", a, b) 797 | err = Decode(b, &r) 798 | if err != nil { 799 | t.Error(err) 800 | } 801 | c := a 802 | c.B = 0 803 | c.d = "" 804 | //r.PS = nil //BUG: how to encode nil pointer? 805 | if !reflect.DeepEqual(r, c) { 806 | t.Errorf("RegStruct got %+v\nneed %+v\n", r, c) 807 | } 808 | } 809 | 810 | func TestRegistStructUnsupported(t *testing.T) { 811 | err := RegStruct(int(0)) 812 | if err == nil { 813 | t.Errorf("RegistStructUnsupported: have err == nil, want non-nil") 814 | } 815 | 816 | info := queryStruct(reflect.TypeOf(doNotSupportTypes)) 817 | if info != nil { 818 | t.Errorf("RegistStructUnsupported: have info == %v, want nil", info) 819 | } 820 | numField := info.numField() 821 | if numField != 0 { 822 | t.Errorf("RegistStructUnsupported: have numField == %v, want 0", numField) 823 | } 824 | field := info.field(0) 825 | if field != nil { 826 | t.Errorf("RegistStructUnsupported: have info == %v, want nil", field) 827 | } 828 | } 829 | 830 | func TestDecodeUvarintOverflow(t *testing.T) { 831 | data := [][]byte{ 832 | []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 833 | []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 834 | } 835 | var d uint 836 | for _, v := range data { 837 | decoder := NewDecoder(v) 838 | err := decoder.Value(&d) 839 | if err == nil { 840 | t.Errorf("DecodeUvarintOverflow: have err == nil, want none-nil") 841 | } else { 842 | //println(err.Error()) 843 | } 844 | } 845 | } 846 | 847 | type sizerOnly struct{ A uint8 } 848 | 849 | func (obj sizerOnly) Size() int { return 1 } 850 | 851 | type encoderOnly struct{ B uint8 } 852 | 853 | func (obj encoderOnly) Encode(buffer []byte) ([]byte, error) { return nil, nil } 854 | 855 | type decoderOnly struct { 856 | C uint8 857 | } 858 | 859 | func (obj *decoderOnly) Decode(buffer []byte) error { return nil } 860 | 861 | type sizeencoderOnly struct { 862 | sizerOnly 863 | encoderOnly 864 | } 865 | type sizedecoderOnly struct { 866 | sizerOnly 867 | decoderOnly 868 | } 869 | type encodedecoderOnly struct { 870 | encoderOnly 871 | decoderOnly 872 | } 873 | type fullSerializer struct { 874 | sizerOnly 875 | encoderOnly 876 | decoderOnly 877 | } 878 | type fullSerializerError struct { 879 | fullSerializer 880 | } 881 | 882 | func (obj *fullSerializerError) Decode(buffer []byte) error { 883 | return fmt.Errorf("expected error") 884 | } 885 | 886 | func TestBinarySerializer(t *testing.T) { 887 | var a sizerOnly 888 | var b encoderOnly 889 | var c decoderOnly 890 | var d sizeencoderOnly 891 | var e sizedecoderOnly 892 | var f encodedecoderOnly 893 | var g fullSerializerError 894 | var h fullSerializer 895 | 896 | testCase := func(data interface{}, testcase int) (info interface{}) { 897 | defer func() { 898 | 899 | _info := recover() 900 | if _info != nil && info == nil { 901 | info = _info 902 | //fmt.Println(info) 903 | } 904 | }() 905 | switch testcase { 906 | case 1: 907 | Sizeof(data) 908 | case 2: 909 | if _, err := Encode(data, nil); err != nil { 910 | info = err 911 | } 912 | 913 | case 3: 914 | buff := make([]byte, 1000) 915 | if err := Decode(buff, data); err != nil { 916 | info = err 917 | } 918 | case 4: 919 | encoder := NewEncoder(100) 920 | if err := encoder.Value(data); err != nil { 921 | info = err 922 | } 923 | } 924 | return 925 | } 926 | 927 | testCode := func(data interface{}) (info interface{}) { 928 | for i := 1; i <= 4; i++ { 929 | if _info := testCase(data, i); _info != nil && info == nil { 930 | info = _info 931 | } 932 | } 933 | return 934 | } 935 | 936 | if info := testCode(&a); info == nil { 937 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 938 | } 939 | if info := testCode(&b); info == nil { 940 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 941 | } 942 | if info := testCode(&c); info == nil { 943 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 944 | } 945 | if info := testCode(&d); info == nil { 946 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 947 | } 948 | if info := testCode(&e); info == nil { 949 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 950 | } 951 | if info := testCode(&f); info == nil { 952 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 953 | } 954 | if info := testCode(&g); info == nil { 955 | t.Errorf("BinarySerializer: have err == nil, want none-nil") 956 | } 957 | if info := testCode(&h); info != nil { 958 | t.Errorf("BinarySerializer: have err == %#v, want nil", info) 959 | } 960 | } 961 | 962 | func TestFastSizeof(t *testing.T) { 963 | type interSize struct { 964 | iter interface{} 965 | size int 966 | } 967 | var cases = []interSize{ 968 | interSize{bool(false), 1}, 969 | interSize{int8(0), 1}, 970 | interSize{uint8(0), 1}, 971 | interSize{int16(0), 2}, 972 | interSize{uint16(0), 2}, 973 | interSize{int32(0), 4}, 974 | interSize{uint32(0), 4}, 975 | interSize{int64(0), 8}, 976 | interSize{uint64(0), 8}, 977 | interSize{float32(0), 4}, 978 | interSize{float64(0), 8}, 979 | interSize{complex64(0), 8}, 980 | interSize{complex128(0), 16}, 981 | interSize{string("hello"), 6}, 982 | 983 | interSize{int(0), 1}, 984 | interSize{uint(0), 1}, 985 | 986 | interSize{[]bool{false, false, true}, 2}, 987 | interSize{[]int8{0}, 2}, 988 | interSize{[]uint8{0}, 2}, 989 | interSize{[]int16{0}, 3}, 990 | interSize{[]uint16{0}, 3}, 991 | interSize{[]int32{0}, 5}, 992 | interSize{[]uint32{0}, 5}, 993 | interSize{[]int64{0}, 9}, 994 | interSize{[]uint64{0}, 9}, 995 | interSize{[]float32{0}, 5}, 996 | interSize{[]float64{0}, 9}, 997 | interSize{[]complex64{0}, 9}, 998 | interSize{[]complex128{0}, 17}, 999 | interSize{[]string{"hello"}, 7}, 1000 | 1001 | interSize{&[]bool{false, false, true}, 2}, 1002 | interSize{&[]int8{0}, 2}, 1003 | interSize{&[]uint8{0}, 2}, 1004 | interSize{&[]int16{0}, 3}, 1005 | interSize{&[]uint16{0}, 3}, 1006 | interSize{&[]int32{0}, 5}, 1007 | interSize{&[]uint32{0}, 5}, 1008 | interSize{&[]int64{0}, 9}, 1009 | interSize{&[]uint64{0}, 9}, 1010 | interSize{&[]float32{0}, 5}, 1011 | interSize{&[]float64{0}, 9}, 1012 | interSize{&[]complex64{0}, 9}, 1013 | interSize{&[]complex128{0}, 17}, 1014 | interSize{&[]string{"hello"}, 7}, 1015 | 1016 | interSize{uintptr(0), -1}, 1017 | interSize{(*[]int)(nil), -1}, 1018 | } 1019 | for i, v := range cases { 1020 | s := fastSizeof(v.iter) 1021 | if s != v.size { 1022 | t.Errorf("%d %#v got %d need %d", i, v.iter, s, v.size) 1023 | } 1024 | } 1025 | } 1026 | 1027 | func TestPackedInts(t *testing.T) { 1028 | type packedInts struct { 1029 | A int16 `binary:"packed"` 1030 | B int32 `binary:"packed"` 1031 | C int64 `binary:"packed"` 1032 | D uint16 `binary:"packed"` 1033 | E uint32 `binary:"packed"` 1034 | F uint64 `binary:"packed"` 1035 | G []uint64 `binary:"packed"` 1036 | } 1037 | var data = packedInts{1, 2, 3, 4, 5, 6, []uint64{7, 8, 9}} 1038 | RegStruct((*packedInts)(nil)) 1039 | b, err := Encode(data, nil) 1040 | if err != nil { 1041 | t.Error(err) 1042 | } 1043 | if s := Sizeof(data); s != len(b) { 1044 | t.Errorf("PackedInts got %+v %+v\nneed %+v\n", len(b), b, s) 1045 | } 1046 | check := []byte{0x2, 0x4, 0x6, 0x4, 0x5, 0x6, 0x3, 0x7, 0x8, 0x9} 1047 | if !reflect.DeepEqual(b, check) { 1048 | t.Errorf("PackedInts %#v\n got %+v\nneed %+v\n", data, b, check) 1049 | } 1050 | 1051 | var dataDecode packedInts 1052 | err = Decode(b, &dataDecode) 1053 | if err != nil { 1054 | t.Error(err) 1055 | } 1056 | if !reflect.DeepEqual(dataDecode, data) { 1057 | t.Errorf("PackedInts got %+v\nneed %+v\n", dataDecode, data) 1058 | } 1059 | } 1060 | 1061 | func TestBools(t *testing.T) { 1062 | type boolset struct { 1063 | A uint8 //0x11 1064 | B bool //true 1065 | C uint8 //0x22 1066 | D []bool //[]bool{true, false, true} 1067 | E bool //true 1068 | F *uint32 //false 1069 | G bool //true 1070 | H uint8 //0x33 1071 | } 1072 | var data = boolset{ 1073 | 0x11, true, 0x22, []bool{true, false, true}, true, nil, true, 0x33, 1074 | } 1075 | b, err := Encode(data, nil) 1076 | if err != nil { 1077 | fmt.Println(err) 1078 | } 1079 | 1080 | size := Sizeof(data) 1081 | if size != len(b) { 1082 | fmt.Printf("EncodeBools got %#v %+v\nneed %+v\n", len(b), b, size) 1083 | } 1084 | check := []byte{0x11, 0xb, 0x22, 0x3, 0x5, 0x33} 1085 | if !reflect.DeepEqual(b, check) { 1086 | t.Errorf("EncodeBools %#v\n got %+v\nneed %+v\n", data, b, check) 1087 | } 1088 | 1089 | var dataDecode boolset 1090 | err = Decode(b, &dataDecode) 1091 | if err != nil { 1092 | t.Error(err) 1093 | } 1094 | if !reflect.DeepEqual(dataDecode, data) { 1095 | t.Errorf("EncodeBools got %+v\nneed %+v\n", dataDecode, data) 1096 | } 1097 | } 1098 | -------------------------------------------------------------------------------- /decoder.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "math" 7 | "reflect" 8 | ) 9 | 10 | // NewDecoder make a new Decoder object with buffer. 11 | func NewDecoder(buffer []byte) *Decoder { 12 | return NewDecoderEndian(buffer, DefaultEndian) 13 | } 14 | 15 | // NewDecoderEndian make a new Decoder object with buffer and endian. 16 | func NewDecoderEndian(buffer []byte, endian Endian) *Decoder { 17 | p := &Decoder{} 18 | p.Init(buffer, endian) 19 | return p 20 | } 21 | 22 | // Decoder is used to decode byte array to go data. 23 | type Decoder struct { 24 | coder 25 | reader io.Reader //for decode from reader only 26 | boolValue byte //last bool value byte 27 | } 28 | 29 | // Skip ignore the next size of bytes for encoding/decoding. 30 | // It will panic If space not enough. 31 | // It will return -1 if size <= 0. 32 | func (decoder *Decoder) Skip(size int) int { 33 | if nil == decoder.reserve(size) { 34 | return -1 35 | } 36 | return size 37 | } 38 | 39 | // reserve returns next size bytes for encoding/decoding. 40 | func (decoder *Decoder) reserve(size int) []byte { 41 | if decoder.reader != nil { //decode from reader 42 | if size > len(decoder.buff) { 43 | decoder.buff = make([]byte, size) 44 | } 45 | buff := decoder.buff[:size] 46 | if n, _ := decoder.reader.Read(buff); n < size { 47 | panic(io.ErrUnexpectedEOF) 48 | } 49 | return buff 50 | } 51 | 52 | return decoder.coder.reserve(size) //decode from bytes buffer 53 | } 54 | 55 | // Init initialize Encoder with buffer and endian. 56 | func (decoder *Decoder) Init(buffer []byte, endian Endian) { 57 | decoder.buff = buffer 58 | decoder.pos = 0 59 | decoder.endian = endian 60 | } 61 | 62 | // Bool decode a bool value from Decoder buffer. 63 | // It will panic if buffer is not enough. 64 | func (decoder *Decoder) Bool() bool { 65 | if decoder.boolBit == 0 { 66 | b := decoder.reserve(1) 67 | decoder.boolValue = b[0] 68 | } 69 | 70 | mask := byte(1 << decoder.boolBit) 71 | decoder.boolBit = (decoder.boolBit + 1) % 8 72 | 73 | x := ((decoder.boolValue & mask) != 0) 74 | return x 75 | } 76 | 77 | // Int8 decode an int8 value from Decoder buffer. 78 | // It will panic if buffer is not enough. 79 | func (decoder *Decoder) Int8() int8 { 80 | return int8(decoder.Uint8()) 81 | } 82 | 83 | // Uint8 decode a uint8 value from Decoder buffer. 84 | // It will panic if buffer is not enough. 85 | func (decoder *Decoder) Uint8() uint8 { 86 | b := decoder.reserve(1) 87 | x := b[0] 88 | return x 89 | } 90 | 91 | // Int16 decode an int16 value from Decoder buffer. 92 | // It will panic if buffer is not enough. 93 | func (decoder *Decoder) Int16(packed bool) int16 { 94 | if packed { 95 | x, _ := decoder.Varint() 96 | return int16(x) 97 | } 98 | 99 | return int16(decoder.Uint16(false)) 100 | } 101 | 102 | // Uint16 decode a uint16 value from Decoder buffer. 103 | // It will panic if buffer is not enough. 104 | func (decoder *Decoder) Uint16(packed bool) uint16 { 105 | if packed { 106 | x, _ := decoder.Uvarint() 107 | return uint16(x) 108 | } 109 | 110 | b := decoder.reserve(2) 111 | x := decoder.endian.Uint16(b) 112 | return x 113 | } 114 | 115 | // Int32 decode an int32 value from Decoder buffer. 116 | // It will panic if buffer is not enough. 117 | func (decoder *Decoder) Int32(packed bool) int32 { 118 | if packed { 119 | x, _ := decoder.Varint() 120 | return int32(x) 121 | } 122 | 123 | return int32(decoder.Uint32(false)) 124 | } 125 | 126 | // Uint32 decode a uint32 value from Decoder buffer. 127 | // It will panic if buffer is not enough. 128 | func (decoder *Decoder) Uint32(packed bool) uint32 { 129 | if packed { 130 | x, _ := decoder.Uvarint() 131 | return uint32(x) 132 | } 133 | 134 | b := decoder.reserve(4) 135 | x := decoder.endian.Uint32(b) 136 | return x 137 | } 138 | 139 | // Int64 decode an int64 value from Decoder buffer. 140 | // It will panic if buffer is not enough. 141 | func (decoder *Decoder) Int64(packed bool) int64 { 142 | if packed { 143 | x, _ := decoder.Varint() 144 | return x 145 | } 146 | 147 | return int64(decoder.Uint64(false)) 148 | } 149 | 150 | // Uint64 decode a uint64 value from Decoder buffer. 151 | // It will panic if buffer is not enough. 152 | func (decoder *Decoder) Uint64(packed bool) uint64 { 153 | if packed { 154 | x, _ := decoder.Uvarint() 155 | return x 156 | } 157 | 158 | b := decoder.reserve(8) 159 | x := decoder.endian.Uint64(b) 160 | return x 161 | } 162 | 163 | // Float32 decode a float32 value from Decoder buffer. 164 | // It will panic if buffer is not enough. 165 | func (decoder *Decoder) Float32() float32 { 166 | x := math.Float32frombits(decoder.Uint32(false)) 167 | return x 168 | } 169 | 170 | // Float64 decode a float64 value from Decoder buffer. 171 | // It will panic if buffer is not enough. 172 | func (decoder *Decoder) Float64() float64 { 173 | x := math.Float64frombits(decoder.Uint64(false)) 174 | return x 175 | } 176 | 177 | // Complex64 decode a complex64 value from Decoder buffer. 178 | // It will panic if buffer is not enough. 179 | func (decoder *Decoder) Complex64() complex64 { 180 | x := complex(decoder.Float32(), decoder.Float32()) 181 | return x 182 | } 183 | 184 | // Complex128 decode a complex128 value from Decoder buffer. 185 | // It will panic if buffer is not enough. 186 | func (decoder *Decoder) Complex128() complex128 { 187 | x := complex(decoder.Float64(), decoder.Float64()) 188 | return x 189 | } 190 | 191 | // String decode a string value from Decoder buffer. 192 | // It will panic if buffer is not enough. 193 | func (decoder *Decoder) String() string { 194 | s, _ := decoder.Uvarint() 195 | size := int(s) 196 | b := decoder.reserve(size) 197 | return string(b) 198 | } 199 | 200 | // Int decode an int value from Decoder buffer. 201 | // It will panic if buffer is not enough. 202 | // It use Varint() to decode as varint(1~10 bytes) 203 | func (decoder *Decoder) Int() int { 204 | n, _ := decoder.Varint() 205 | return int(n) 206 | } 207 | 208 | // Uint decode a uint value from Decoder buffer. 209 | // It will panic if buffer is not enough. 210 | // It use Uvarint() to decode as uvarint(1~10 bytes) 211 | func (decoder *Decoder) Uint() uint { 212 | n, _ := decoder.Uvarint() 213 | return uint(n) 214 | } 215 | 216 | // Varint decode an int64 value from Decoder buffer with varint(1~10 bytes). 217 | // It will panic if buffer is not enough. 218 | func (decoder *Decoder) Varint() (int64, int) { 219 | ux, n := decoder.Uvarint() // ok to continue in presence of error 220 | return ToVarint(ux), n 221 | } 222 | 223 | // Uvarint decode a uint64 value from Decoder buffer with varint(1~10 bytes). 224 | // It will panic if buffer is not enough. 225 | // It will return n <= 0 if varint error 226 | func (decoder *Decoder) Uvarint() (uint64, int) { 227 | var x uint64 228 | var bit uint 229 | var i int 230 | for i = 0; i < MaxVarintLen64; i++ { 231 | b := decoder.Uint8() 232 | x |= uint64(b&0x7f) << bit 233 | if b < 0x80 { 234 | if i > 9 || i == 9 && b > 1 { 235 | break // overflow 236 | } 237 | return x, i + 1 238 | } 239 | bit += 7 240 | } 241 | //return 0, 0 242 | panic(fmt.Errorf("binary.Decoder.Uvarint: overflow 64-bits value(pos:%d/%d)", decoder.Len(), decoder.Cap())) 243 | } 244 | 245 | // Value decode an interface value from Encoder buffer. 246 | // x must be interface of pointer for modify. 247 | // It will return none-nil error if x contains unsupported types 248 | // or buffer is not enough. 249 | // It will check if x implements interface BinaryEncoder and use x.Encode first. 250 | func (decoder *Decoder) Value(x interface{}) (err error) { 251 | defer func() { 252 | if info := recover(); info != nil { 253 | err = info.(error) 254 | assert(err != nil, info) 255 | } 256 | }() 257 | 258 | decoder.resetBoolCoder() //reset bool reader 259 | 260 | if decoder.fastValue(x) { //fast value path 261 | return nil 262 | } 263 | 264 | v := reflect.ValueOf(x) 265 | 266 | if p, ok := x.(BinaryDecoder); ok { 267 | size := 0 268 | if sizer, _ok := x.(BinarySizer); _ok { //interface verification 269 | size = sizer.Size() 270 | } else { 271 | panic(fmt.Errorf("expect but not BinarySizer: %s", v.Type().String())) 272 | } 273 | if _, _ok := x.(BinaryEncoder); !_ok { //interface verification 274 | panic(fmt.Errorf("unexpect but not BinaryEncoder: %s", v.Type().String())) 275 | } 276 | err := p.Decode(decoder.buff[decoder.pos:]) 277 | if err != nil { 278 | return err 279 | } 280 | decoder.reserve(size) 281 | return nil 282 | } 283 | 284 | if _, _ok := x.(BinarySizer); _ok { //interface verification 285 | panic(fmt.Errorf("unexpected BinarySizer: %s", v.Type().String())) 286 | } 287 | if _, _ok := x.(BinaryEncoder); _ok { //interface verification 288 | panic(fmt.Errorf("unexpected BinaryEncoder: %s", v.Type().String())) 289 | } 290 | 291 | if v.Kind() == reflect.Ptr { //only support decode for pointer interface 292 | return decoder.value(v, true, false) 293 | } 294 | 295 | return fmt.Errorf("binary.Decoder.Value: non-pointer type %s", v.Type().String()) 296 | } 297 | 298 | func (decoder *Decoder) value(v reflect.Value, topLevel bool, packed bool) error { 299 | // check Packer interface for every value is perfect 300 | // but decoder is too costly 301 | // 302 | // if t := v.Type(); t.Implements(tUnpacker) { 303 | // if !t.Implements(tPacker) { //interface verification 304 | // panic(fmt.Errorf("unexpect but not Packer: %s", v.Type().String())) 305 | // } 306 | // if !t.Implements(tSizer) { //interface verification 307 | // panic(fmt.Errorf("expect but not Sizer: %s", t.String())) 308 | // } 309 | 310 | // unpacker := v.Interface().(PackUnpacker) 311 | // size := unpacker.Size() 312 | // err := unpacker.Unpack(decoder.buff[decoder.pos:]) 313 | // if err != nil { 314 | // return err 315 | // } 316 | // decoder.reserve(size) 317 | // return nil 318 | // } else { 319 | // //interface verification 320 | // if t.Implements(tSizer) { 321 | // panic(fmt.Errorf("unexpected Sizer: %s", t.String())) 322 | // } 323 | // if t.Implements(tPacker) { 324 | // panic(fmt.Errorf("unexpected Packer: %s", t.String())) 325 | // } 326 | // } 327 | 328 | switch k := v.Kind(); k { 329 | case reflect.Int: 330 | v.SetInt(int64(decoder.Int())) 331 | case reflect.Uint: 332 | v.SetUint(uint64(decoder.Uint())) 333 | 334 | case reflect.Bool: 335 | v.SetBool(decoder.Bool()) 336 | 337 | case reflect.Int8: 338 | v.SetInt(int64(decoder.Int8())) 339 | case reflect.Int16: 340 | v.SetInt(int64(decoder.Int16(packed))) 341 | case reflect.Int32: 342 | v.SetInt(int64(decoder.Int32(packed))) 343 | case reflect.Int64: 344 | v.SetInt(decoder.Int64(packed)) 345 | 346 | case reflect.Uint8: 347 | v.SetUint(uint64(decoder.Uint8())) 348 | case reflect.Uint16: 349 | v.SetUint(uint64(decoder.Uint16(packed))) 350 | case reflect.Uint32: 351 | v.SetUint(uint64(decoder.Uint32(packed))) 352 | case reflect.Uint64: 353 | v.SetUint(decoder.Uint64(packed)) 354 | 355 | case reflect.Float32: 356 | v.SetFloat(float64(decoder.Float32())) 357 | case reflect.Float64: 358 | v.SetFloat(decoder.Float64()) 359 | 360 | case reflect.Complex64: 361 | v.SetComplex(complex128(decoder.Complex64())) 362 | 363 | case reflect.Complex128: 364 | v.SetComplex(decoder.Complex128()) 365 | 366 | case reflect.String: 367 | v.SetString(decoder.String()) 368 | 369 | case reflect.Slice, reflect.Array: 370 | if !validUserType(v.Type().Elem()) { //verify array element is valid 371 | return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) 372 | } 373 | if decoder.boolArray(v) < 0 { //deal with bool array first 374 | s, _ := decoder.Uvarint() 375 | size := int(s) 376 | if size > 0 && k == reflect.Slice { //make a new slice 377 | ns := reflect.MakeSlice(v.Type(), size, size) 378 | v.Set(ns) 379 | } 380 | 381 | l := v.Len() 382 | for i := 0; i < size; i++ { 383 | if i < l { 384 | assert(decoder.value(v.Index(i), false, packed) == nil, "") 385 | } else { 386 | skiped := decoder.skipByType(v.Type().Elem(), packed) 387 | assert(skiped >= 0, v.Type().Elem().String()) //I'm sure here cannot find unsupported type 388 | } 389 | } 390 | } 391 | case reflect.Map: 392 | t := v.Type() 393 | kt := t.Key() 394 | vt := t.Elem() 395 | if !validUserType(kt) || 396 | !validUserType(vt) { //verify map key and value type are both valid 397 | return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) 398 | } 399 | 400 | if v.IsNil() { 401 | newmap := reflect.MakeMap(v.Type()) 402 | v.Set(newmap) 403 | } 404 | 405 | s, _ := decoder.Uvarint() 406 | size := int(s) 407 | for i := 0; i < size; i++ { 408 | key := reflect.New(kt).Elem() 409 | value := reflect.New(vt).Elem() 410 | assert(decoder.value(key, false, packed) == nil, "") 411 | assert(decoder.value(value, false, packed) == nil, "") 412 | v.SetMapIndex(key, value) 413 | } 414 | case reflect.Struct: 415 | return queryStruct(v.Type()).decode(decoder, v) 416 | 417 | default: 418 | if newPtr(v, decoder, topLevel) { 419 | if !v.IsNil() { 420 | return decoder.value(v.Elem(), false, packed) 421 | } 422 | } else { 423 | return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) 424 | } 425 | } 426 | return nil 427 | } 428 | 429 | func (decoder *Decoder) fastValue(x interface{}) bool { 430 | switch d := x.(type) { 431 | case *int: 432 | *d = decoder.Int() 433 | case *uint: 434 | *d = decoder.Uint() 435 | 436 | case *bool: 437 | *d = decoder.Bool() 438 | case *int8: 439 | *d = decoder.Int8() 440 | case *uint8: 441 | *d = decoder.Uint8() 442 | 443 | case *int16: 444 | *d = decoder.Int16(false) 445 | case *uint16: 446 | *d = decoder.Uint16(false) 447 | 448 | case *int32: 449 | *d = decoder.Int32(false) 450 | case *uint32: 451 | *d = decoder.Uint32(false) 452 | case *float32: 453 | *d = decoder.Float32() 454 | 455 | case *int64: 456 | *d = decoder.Int64(false) 457 | case *uint64: 458 | *d = decoder.Uint64(false) 459 | case *float64: 460 | *d = decoder.Float64() 461 | case *complex64: 462 | *d = decoder.Complex64() 463 | 464 | case *complex128: 465 | *d = decoder.Complex128() 466 | 467 | case *string: 468 | *d = decoder.String() 469 | 470 | case *[]bool: 471 | s, _ := decoder.Uvarint() 472 | l := int(s) 473 | *d = make([]bool, l) 474 | var b []byte 475 | for i := 0; i < l; i++ { 476 | _, bit := i/8, i%8 477 | mask := byte(1 << uint(bit)) 478 | if bit == 0 { 479 | b = decoder.reserve(1) 480 | } 481 | x := ((b[0] & mask) != 0) 482 | (*d)[i] = x 483 | } 484 | 485 | case *[]int: 486 | s, _ := decoder.Uvarint() 487 | l := int(s) 488 | *d = make([]int, l) 489 | for i := 0; i < l; i++ { 490 | (*d)[i] = decoder.Int() 491 | } 492 | case *[]uint: 493 | s, _ := decoder.Uvarint() 494 | l := int(s) 495 | *d = make([]uint, l) 496 | for i := 0; i < l; i++ { 497 | (*d)[i] = decoder.Uint() 498 | } 499 | 500 | case *[]int8: 501 | s, _ := decoder.Uvarint() 502 | l := int(s) 503 | *d = make([]int8, l) 504 | for i := 0; i < l; i++ { 505 | (*d)[i] = decoder.Int8() 506 | } 507 | case *[]uint8: 508 | s, _ := decoder.Uvarint() 509 | l := int(s) 510 | *d = make([]uint8, l) 511 | for i := 0; i < l; i++ { 512 | (*d)[i] = decoder.Uint8() 513 | } 514 | case *[]int16: 515 | s, _ := decoder.Uvarint() 516 | l := int(s) 517 | *d = make([]int16, l) 518 | for i := 0; i < l; i++ { 519 | (*d)[i] = decoder.Int16(false) 520 | } 521 | case *[]uint16: 522 | s, _ := decoder.Uvarint() 523 | l := int(s) 524 | *d = make([]uint16, l) 525 | for i := 0; i < l; i++ { 526 | (*d)[i] = decoder.Uint16(false) 527 | } 528 | case *[]int32: 529 | s, _ := decoder.Uvarint() 530 | l := int(s) 531 | *d = make([]int32, l) 532 | for i := 0; i < l; i++ { 533 | (*d)[i] = decoder.Int32(false) 534 | } 535 | case *[]uint32: 536 | s, _ := decoder.Uvarint() 537 | l := int(s) 538 | *d = make([]uint32, l) 539 | for i := 0; i < l; i++ { 540 | (*d)[i] = decoder.Uint32(false) 541 | } 542 | case *[]int64: 543 | s, _ := decoder.Uvarint() 544 | l := int(s) 545 | *d = make([]int64, l) 546 | for i := 0; i < l; i++ { 547 | (*d)[i] = decoder.Int64(false) 548 | } 549 | case *[]uint64: 550 | s, _ := decoder.Uvarint() 551 | l := int(s) 552 | *d = make([]uint64, l) 553 | for i := 0; i < l; i++ { 554 | (*d)[i] = decoder.Uint64(false) 555 | } 556 | case *[]float32: 557 | s, _ := decoder.Uvarint() 558 | l := int(s) 559 | *d = make([]float32, l) 560 | for i := 0; i < l; i++ { 561 | (*d)[i] = decoder.Float32() 562 | } 563 | case *[]float64: 564 | s, _ := decoder.Uvarint() 565 | l := int(s) 566 | *d = make([]float64, l) 567 | for i := 0; i < l; i++ { 568 | (*d)[i] = decoder.Float64() 569 | } 570 | case *[]complex64: 571 | s, _ := decoder.Uvarint() 572 | l := int(s) 573 | *d = make([]complex64, l) 574 | for i := 0; i < l; i++ { 575 | (*d)[i] = decoder.Complex64() 576 | } 577 | case *[]complex128: 578 | s, _ := decoder.Uvarint() 579 | l := int(s) 580 | *d = make([]complex128, l) 581 | for i := 0; i < l; i++ { 582 | (*d)[i] = decoder.Complex128() 583 | } 584 | case *[]string: 585 | s, _ := decoder.Uvarint() 586 | l := int(s) 587 | *d = make([]string, l) 588 | for i := 0; i < l; i++ { 589 | (*d)[i] = decoder.String() 590 | } 591 | default: 592 | return false 593 | } 594 | return true 595 | } 596 | 597 | func (decoder *Decoder) skipByType(t reflect.Type, packed bool) int { 598 | if s := fixedTypeSize(t); s > 0 { 599 | if packedType := packedIntsType(t); packedType > 0 && packed { 600 | switch packedType { 601 | case _SignedInts: 602 | _, n := decoder.Varint() 603 | return n 604 | case _UnsignedInts: 605 | _, n := decoder.Uvarint() 606 | return n 607 | } 608 | } else { 609 | decoder.Skip(s) 610 | return s 611 | } 612 | } 613 | switch t.Kind() { 614 | case reflect.Ptr: 615 | if isNotNil := decoder.Bool(); isNotNil { 616 | return decoder.skipByType(t.Elem(), packed) + 1 617 | } 618 | return 1 619 | case reflect.Bool: 620 | decoder.Bool() 621 | return 1 622 | case reflect.Int: 623 | _, n := decoder.Varint() 624 | return n 625 | case reflect.Uint: 626 | _, n := decoder.Uvarint() 627 | return n 628 | case reflect.String: 629 | s, n := decoder.Uvarint() 630 | size := int(s) //string length and data 631 | decoder.Skip(size) 632 | return size + n 633 | case reflect.Slice, reflect.Array: 634 | s, sLen := decoder.Uvarint() 635 | cnt := int(s) 636 | elemtype := t.Elem() 637 | if s := fixedTypeSize(elemtype); s > 0 { 638 | size := cnt * s 639 | decoder.Skip(size) 640 | return size 641 | } 642 | 643 | if elemtype.Kind() == reflect.Bool { //compressed bool array 644 | totalSize := sizeofBoolArray(cnt) 645 | size := totalSize - SizeofUvarint(uint64(cnt)) //cnt has been read 646 | decoder.Skip(size) 647 | return totalSize 648 | } 649 | 650 | sum := sLen //array size 651 | for i, n := 0, cnt; i < n; i++ { 652 | s := decoder.skipByType(elemtype, packed) 653 | assert(s >= 0, "skip fail: "+elemtype.String()) //I'm sure here cannot find unsupported type 654 | sum += s 655 | } 656 | return sum 657 | case reflect.Map: 658 | s, sLen := decoder.Uvarint() 659 | cnt := int(s) 660 | kt := t.Key() 661 | vt := t.Elem() 662 | sum := sLen //array size 663 | for i, n := 0, cnt; i < n; i++ { 664 | sum += decoder.skipByType(kt, packed) 665 | sum += decoder.skipByType(vt, packed) 666 | } 667 | return sum 668 | 669 | case reflect.Struct: 670 | return queryStruct(t).decodeSkipByType(decoder, t, packed) 671 | } 672 | return -1 673 | } 674 | 675 | // decode bool array 676 | func (decoder *Decoder) boolArray(v reflect.Value) int { 677 | if k := v.Kind(); k == reflect.Slice || k == reflect.Array { 678 | if v.Type().Elem().Kind() == reflect.Bool { 679 | _l, _ := decoder.Uvarint() 680 | l := int(_l) 681 | if k == reflect.Slice && l > 0 { //make a new slice 682 | v.Set(reflect.MakeSlice(v.Type(), l, l)) 683 | } 684 | var b []byte 685 | for i := 0; i < l; i++ { 686 | _, bit := i/8, i%8 687 | mask := byte(1 << uint(bit)) 688 | if bit == 0 { 689 | b = decoder.reserve(1) 690 | } 691 | x := ((b[0] & mask) != 0) 692 | v.Index(i).SetBool(x) 693 | } 694 | return sizeofBoolArray(l) 695 | } 696 | } 697 | return -1 698 | } 699 | -------------------------------------------------------------------------------- /encoder.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "reflect" 7 | ) 8 | 9 | // NewEncoder make a new Encoder object with buffer size. 10 | func NewEncoder(size int) *Encoder { 11 | return NewEncoderEndian(size, DefaultEndian) 12 | } 13 | 14 | // NewEncoderBuffer make a new Encoder object with buffer. 15 | func NewEncoderBuffer(buffer []byte) *Encoder { 16 | p := &Encoder{} 17 | //assert(buffer != nil, "nil buffer") 18 | p.buff = buffer 19 | p.endian = DefaultEndian 20 | p.pos = 0 21 | return p 22 | } 23 | 24 | // NewEncoderEndian make a new Encoder object with buffer size and endian. 25 | func NewEncoderEndian(size int, endian Endian) *Encoder { 26 | p := &Encoder{} 27 | p.Init(size, endian) 28 | return p 29 | } 30 | 31 | // Encoder is used to encode go data to byte array. 32 | type Encoder struct { 33 | coder 34 | } 35 | 36 | // Init initialize Encoder with buffer size and endian. 37 | func (encoder *Encoder) Init(size int, endian Endian) { 38 | encoder.buff = make([]byte, size) 39 | encoder.pos = 0 40 | encoder.endian = endian 41 | } 42 | 43 | // ResizeBuffer confirm that len(buffer) >= size and alloc larger buffer if necessary 44 | // It will call Reset to initial encoder state of buffer 45 | func (encoder *Encoder) ResizeBuffer(size int) bool { 46 | ok := len(encoder.buff) < size 47 | if ok { 48 | encoder.buff = make([]byte, size) 49 | } 50 | encoder.Reset() 51 | return ok 52 | } 53 | 54 | // Bool encode a bool value to Encoder buffer. 55 | // It will panic if buffer is not enough. 56 | func (encoder *Encoder) Bool(x bool) { 57 | if encoder.boolBit == 0 { 58 | b := encoder.reserve(1) 59 | b[0] = 0 60 | encoder.boolPos = encoder.pos - 1 61 | } 62 | 63 | if mask := byte(1 << encoder.boolBit); x { 64 | encoder.buff[encoder.boolPos] |= mask 65 | } 66 | encoder.boolBit = (encoder.boolBit + 1) % 8 67 | } 68 | 69 | // Int8 encode an int8 value to Encoder buffer. 70 | // It will panic if buffer is not enough. 71 | func (encoder *Encoder) Int8(x int8) { 72 | encoder.Uint8(uint8(x)) 73 | } 74 | 75 | // Uint8 encode a uint8 value to Encoder buffer. 76 | // It will panic if buffer is not enough. 77 | func (encoder *Encoder) Uint8(x uint8) { 78 | b := encoder.reserve(1) 79 | b[0] = x 80 | } 81 | 82 | // Int16 encode an int16 value to Encoder buffer. 83 | // It will panic if buffer is not enough. 84 | func (encoder *Encoder) Int16(x int16, packed bool) { 85 | if packed { 86 | encoder.Varint(int64(x)) 87 | } else { 88 | encoder.Uint16(uint16(x), false) 89 | } 90 | 91 | } 92 | 93 | // Uint16 encode a uint16 value to Encoder buffer. 94 | // It will panic if buffer is not enough. 95 | func (encoder *Encoder) Uint16(x uint16, packed bool) { 96 | if packed { 97 | encoder.Uvarint(uint64(x)) 98 | } else { 99 | b := encoder.reserve(2) 100 | encoder.endian.PutUint16(b, x) 101 | } 102 | } 103 | 104 | // Int32 encode an int32 value to Encoder buffer. 105 | // It will panic if buffer is not enough. 106 | func (encoder *Encoder) Int32(x int32, packed bool) { 107 | if packed { 108 | encoder.Varint(int64(x)) 109 | } else { 110 | encoder.Uint32(uint32(x), false) 111 | } 112 | } 113 | 114 | // Uint32 encode a uint32 value to Encoder buffer. 115 | // It will panic if buffer is not enough. 116 | func (encoder *Encoder) Uint32(x uint32, packed bool) { 117 | if packed { 118 | encoder.Uvarint(uint64(x)) 119 | } else { 120 | b := encoder.reserve(4) 121 | encoder.endian.PutUint32(b, x) 122 | } 123 | } 124 | 125 | // Int64 encode an int64 value to Encoder buffer. 126 | // It will panic if buffer is not enough. 127 | func (encoder *Encoder) Int64(x int64, packed bool) { 128 | if packed { 129 | encoder.Varint(x) 130 | } else { 131 | encoder.Uint64(uint64(x), false) 132 | } 133 | } 134 | 135 | // Uint64 encode a uint64 value to Encoder buffer. 136 | // It will panic if buffer is not enough. 137 | func (encoder *Encoder) Uint64(x uint64, packed bool) { 138 | if packed { 139 | encoder.Uvarint(x) 140 | } else { 141 | b := encoder.reserve(8) 142 | encoder.endian.PutUint64(b, x) 143 | } 144 | } 145 | 146 | // Float32 encode a float32 value to Encoder buffer. 147 | // It will panic if buffer is not enough. 148 | func (encoder *Encoder) Float32(x float32) { 149 | encoder.Uint32(math.Float32bits(x), false) 150 | } 151 | 152 | // Float64 encode a float64 value to Encoder buffer. 153 | // It will panic if buffer is not enough. 154 | func (encoder *Encoder) Float64(x float64) { 155 | encoder.Uint64(math.Float64bits(x), false) 156 | } 157 | 158 | // Complex64 encode a complex64 value to Encoder buffer. 159 | // It will panic if buffer is not enough. 160 | func (encoder *Encoder) Complex64(x complex64) { 161 | encoder.Uint32(math.Float32bits(real(x)), false) 162 | encoder.Uint32(math.Float32bits(imag(x)), false) 163 | } 164 | 165 | // Complex128 encode a complex128 value to Encoder buffer. 166 | // It will panic if buffer is not enough. 167 | func (encoder *Encoder) Complex128(x complex128) { 168 | encoder.Uint64(math.Float64bits(real(x)), false) 169 | encoder.Uint64(math.Float64bits(imag(x)), false) 170 | } 171 | 172 | // String encode a string value to Encoder buffer. 173 | // It will panic if buffer is not enough. 174 | func (encoder *Encoder) String(x string) { 175 | _b := []byte(x) 176 | size := len(_b) 177 | encoder.Uvarint(uint64(size)) 178 | buff := encoder.reserve(size) 179 | copy(buff, _b) 180 | } 181 | 182 | // Int encode an int value to Encoder buffer. 183 | // It will panic if buffer is not enough. 184 | // It use Varint() to encode as varint(1~10 bytes) 185 | func (encoder *Encoder) Int(x int) { 186 | encoder.Varint(int64(x)) 187 | } 188 | 189 | // Uint encode a uint value to Encoder buffer. 190 | // It will panic if buffer is not enough. 191 | // It use Uvarint() to encode as uvarint(1~10 bytes) 192 | func (encoder *Encoder) Uint(x uint) { 193 | encoder.Uvarint(uint64(x)) 194 | } 195 | 196 | // Varint encode an int64 value to Encoder buffer with varint(1~10 bytes). 197 | // It will panic if buffer is not enough. 198 | func (encoder *Encoder) Varint(x int64) int { 199 | return encoder.Uvarint(ToUvarint(x)) 200 | } 201 | 202 | // Uvarint encode a uint64 value to Encoder buffer with varint(1~10 bytes). 203 | // It will panic if buffer is not enough. 204 | func (encoder *Encoder) Uvarint(x uint64) int { 205 | i, _x := 0, x 206 | for ; _x >= 0x80; _x >>= 7 { 207 | encoder.Uint8(byte(_x) | 0x80) 208 | i++ 209 | } 210 | encoder.Uint8(byte(_x)) 211 | return i + 1 212 | } 213 | 214 | // Value encode an interface value to Encoder buffer. 215 | // It will return none-nil error if x contains unsupported types 216 | // or buffer is not enough. 217 | // It will check if x implements interface BinaryEncoder and use x.Encode first. 218 | func (encoder *Encoder) Value(x interface{}) (err error) { 219 | defer func() { 220 | if e := recover(); e != nil { 221 | err = e.(error) 222 | } 223 | }() 224 | 225 | encoder.resetBoolCoder() //reset bool writer 226 | 227 | if encoder.fastValue(x) { //fast value path 228 | return nil 229 | } 230 | 231 | v := reflect.ValueOf(x) 232 | 233 | if p, ok := x.(BinaryEncoder); ok { 234 | if _, _ok := x.(BinarySizer); !_ok { //interface verification 235 | panic(fmt.Errorf("expect but not BinarySizer: %s", v.Type().String())) 236 | } 237 | 238 | r, err := p.Encode(encoder.buff[encoder.pos:]) 239 | if err == nil { 240 | encoder.reserve(len(r)) 241 | } 242 | return err 243 | } 244 | 245 | if _, _ok := x.(BinarySizer); _ok { //interface verification 246 | panic(fmt.Errorf("unexpected BinarySizer: %s", v.Type().String())) 247 | } 248 | 249 | return encoder.value(reflect.Indirect(v), false) 250 | } 251 | 252 | func (encoder *Encoder) fastValue(x interface{}) bool { 253 | switch d := x.(type) { 254 | case int: 255 | encoder.Int(d) 256 | case uint: 257 | encoder.Uint(d) 258 | 259 | case bool: 260 | encoder.Bool(d) 261 | case int8: 262 | encoder.Int8(d) 263 | case uint8: 264 | encoder.Uint8(d) 265 | case int16: 266 | encoder.Int16(d, false) 267 | case uint16: 268 | encoder.Uint16(d, false) 269 | case int32: 270 | encoder.Int32(d, false) 271 | case uint32: 272 | encoder.Uint32(d, false) 273 | case float32: 274 | encoder.Float32(d) 275 | case int64: 276 | encoder.Int64(d, false) 277 | case uint64: 278 | encoder.Uint64(d, false) 279 | case float64: 280 | encoder.Float64(d) 281 | case complex64: 282 | encoder.Complex64(d) 283 | case complex128: 284 | encoder.Complex128(d) 285 | case string: 286 | encoder.String(d) 287 | case []bool: 288 | l := len(d) 289 | encoder.Uvarint(uint64(l)) 290 | var b []byte 291 | for i := 0; i < l; i++ { 292 | bit := i % 8 293 | mask := byte(1 << uint(bit)) 294 | if bit == 0 { 295 | b = encoder.reserve(1) 296 | b[0] = 0 297 | } 298 | if x := d[i]; x { 299 | b[0] |= mask 300 | } 301 | } 302 | 303 | case []int8: 304 | l := len(d) 305 | encoder.Uvarint(uint64(len(d))) 306 | for i := 0; i < l; i++ { 307 | encoder.Int8(d[i]) 308 | } 309 | case []uint8: 310 | l := len(d) 311 | encoder.Uvarint(uint64(len(d))) 312 | for i := 0; i < l; i++ { 313 | encoder.Uint8(d[i]) 314 | } 315 | case []int16: 316 | l := len(d) 317 | encoder.Uvarint(uint64(len(d))) 318 | for i := 0; i < l; i++ { 319 | encoder.Int16(d[i], false) 320 | } 321 | case []uint16: 322 | l := len(d) 323 | encoder.Uvarint(uint64(len(d))) 324 | for i := 0; i < l; i++ { 325 | encoder.Uint16(d[i], false) 326 | } 327 | 328 | case []int32: 329 | l := len(d) 330 | encoder.Uvarint(uint64(len(d))) 331 | for i := 0; i < l; i++ { 332 | encoder.Int32(d[i], false) 333 | } 334 | case []uint32: 335 | l := len(d) 336 | encoder.Uvarint(uint64(len(d))) 337 | for i := 0; i < l; i++ { 338 | encoder.Uint32(d[i], false) 339 | } 340 | case []int64: 341 | l := len(d) 342 | encoder.Uvarint(uint64(len(d))) 343 | for i := 0; i < l; i++ { 344 | encoder.Int64(d[i], false) 345 | } 346 | case []uint64: 347 | l := len(d) 348 | encoder.Uvarint(uint64(len(d))) 349 | for i := 0; i < l; i++ { 350 | encoder.Uint64(d[i], false) 351 | } 352 | case []float32: 353 | l := len(d) 354 | encoder.Uvarint(uint64(len(d))) 355 | for i := 0; i < l; i++ { 356 | encoder.Float32(d[i]) 357 | } 358 | case []float64: 359 | l := len(d) 360 | encoder.Uvarint(uint64(len(d))) 361 | for i := 0; i < l; i++ { 362 | encoder.Float64(d[i]) 363 | } 364 | case []complex64: 365 | l := len(d) 366 | encoder.Uvarint(uint64(len(d))) 367 | for i := 0; i < l; i++ { 368 | encoder.Complex64(d[i]) 369 | } 370 | case []complex128: 371 | l := len(d) 372 | encoder.Uvarint(uint64(len(d))) 373 | for i := 0; i < l; i++ { 374 | encoder.Complex128(d[i]) 375 | } 376 | case []string: 377 | l := len(d) 378 | encoder.Uvarint(uint64(len(d))) 379 | for i := 0; i < l; i++ { 380 | encoder.String(d[i]) 381 | } 382 | case []int: 383 | l := len(d) 384 | encoder.Uvarint(uint64(len(d))) 385 | for i := 0; i < l; i++ { 386 | encoder.Int(d[i]) 387 | } 388 | case []uint: 389 | l := len(d) 390 | encoder.Uvarint(uint64(len(d))) 391 | for i := 0; i < l; i++ { 392 | encoder.Uint(d[i]) 393 | } 394 | default: 395 | return false 396 | } 397 | return true 398 | 399 | } 400 | 401 | func (encoder *Encoder) value(v reflect.Value, packed bool) error { 402 | // check Packer interface for every value is perfect 403 | // but encoder is too costly 404 | // 405 | // if t := v.Type(); t.Implements(tPacker) { 406 | // if !t.Implements(tSizer) { //interface verification 407 | // panic(fmt.Errorf("pected but not Sizer: %s", t.String())) 408 | // } 409 | // packer := v.Interface().(Packer) 410 | // reault, err := packer.Pack(encoder.buff[encoder.pos:]) 411 | // if err == nil { 412 | // encoder.reserve(len(reault)) 413 | // } 414 | // return err 415 | // } else { 416 | // if t.Implements(tSizer) { //interface verification 417 | // panic(fmt.Errorf("unexpected Sizer: %s", v.Type().String())) 418 | // } 419 | // } 420 | 421 | switch k := v.Kind(); k { 422 | case reflect.Int: 423 | encoder.Int(int(v.Int())) 424 | case reflect.Uint: 425 | encoder.Uint(uint(v.Uint())) 426 | 427 | case reflect.Bool: 428 | encoder.Bool(v.Bool()) 429 | 430 | case reflect.Int8: 431 | encoder.Int8(int8(v.Int())) 432 | case reflect.Int16: 433 | encoder.Int16(int16(v.Int()), packed) 434 | case reflect.Int32: 435 | encoder.Int32(int32(v.Int()), packed) 436 | case reflect.Int64: 437 | encoder.Int64(v.Int(), packed) 438 | 439 | case reflect.Uint8: 440 | encoder.Uint8(uint8(v.Uint())) 441 | case reflect.Uint16: 442 | encoder.Uint16(uint16(v.Uint()), packed) 443 | case reflect.Uint32: 444 | encoder.Uint32(uint32(v.Uint()), packed) 445 | case reflect.Uint64: 446 | encoder.Uint64(v.Uint(), packed) 447 | 448 | case reflect.Float32: 449 | encoder.Float32(float32(v.Float())) 450 | case reflect.Float64: 451 | encoder.Float64(v.Float()) 452 | 453 | case reflect.Complex64: 454 | x := v.Complex() 455 | encoder.Complex64(complex64(x)) 456 | 457 | case reflect.Complex128: 458 | x := v.Complex() 459 | encoder.Complex128(x) 460 | 461 | case reflect.String: 462 | encoder.String(v.String()) 463 | 464 | case reflect.Slice, reflect.Array: 465 | if !validUserType(v.Type().Elem()) { //verify array element is valid 466 | return fmt.Errorf("binary.Encoder.Value: unsupported type %s", v.Type().String()) 467 | } 468 | if encoder.boolArray(v) < 0 { //deal with bool array first 469 | l := v.Len() 470 | encoder.Uvarint(uint64(l)) 471 | for i := 0; i < l; i++ { 472 | assert(encoder.value(v.Index(i), packed) == nil, "") 473 | } 474 | } 475 | case reflect.Map: 476 | t := v.Type() 477 | kt := t.Key() 478 | vt := t.Elem() 479 | if !validUserType(kt) || 480 | !validUserType(vt) { //verify map key and value type are both valid 481 | return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) 482 | } 483 | 484 | keys := v.MapKeys() 485 | l := len(keys) 486 | encoder.Uvarint(uint64(l)) 487 | for i := 0; i < l; i++ { 488 | key := keys[i] 489 | assert(encoder.value(key, packed) == nil, "") 490 | assert(encoder.value(v.MapIndex(key), packed) == nil, "") 491 | } 492 | case reflect.Struct: 493 | return queryStruct(v.Type()).encode(encoder, v) 494 | 495 | case reflect.Ptr: 496 | if !validUserType(v.Type()) { 497 | return fmt.Errorf("binary.Encoder.Value: unsupported type %s", v.Type().String()) 498 | } 499 | if !v.IsNil() { 500 | encoder.Bool(true) 501 | if e := v.Elem(); e.Kind() != reflect.Ptr { 502 | return encoder.value(e, packed) 503 | } 504 | } else { 505 | encoder.Bool(false) 506 | // if encoder.nilPointer(v.Type()) < 0 { 507 | // return fmt.Errorf("binary.Encoder.Value: unsupported type [%s]", v.Type().String()) 508 | // } 509 | } 510 | // case reflect.Invalid://BUG: it will panic to get zero.Type 511 | // return fmt.Errorf("binary.Encoder.Value: unsupported type [%s]", v.Kind().String()) 512 | default: 513 | return fmt.Errorf("binary.Encoder.Value: unsupported type [%s]", v.Type().String()) 514 | } 515 | return nil 516 | } 517 | 518 | // encode bool array 519 | func (encoder *Encoder) boolArray(v reflect.Value) int { 520 | if k := v.Kind(); k == reflect.Slice || k == reflect.Array { 521 | if v.Type().Elem().Kind() == reflect.Bool { 522 | l := v.Len() 523 | encoder.Uvarint(uint64(l)) 524 | var b []byte 525 | for i := 0; i < l; i++ { 526 | bit := i % 8 527 | mask := byte(1 << uint(bit)) 528 | if bit == 0 { 529 | b = encoder.reserve(1) 530 | b[0] = 0 531 | } 532 | if x := v.Index(i).Bool(); x { 533 | b[0] |= mask 534 | } 535 | } 536 | return sizeofBoolArray(l) 537 | } 538 | } 539 | return -1 540 | } 541 | -------------------------------------------------------------------------------- /endian.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | // Endian is a ByteOrder specifies how to convert byte sequences into 4 | // 16-, 32-, or 64-bit unsigned integers. 5 | type Endian interface { 6 | Uint16([]byte) uint16 7 | Uint32([]byte) uint32 8 | Uint64([]byte) uint64 9 | PutUint16([]byte, uint16) 10 | PutUint32([]byte, uint32) 11 | PutUint64([]byte, uint64) 12 | String() string 13 | } 14 | 15 | var ( 16 | // LittleEndian is the little-endian implementation of Endian. 17 | LittleEndian littleEndian 18 | // BigEndian is the big-endian implementation of Endian. 19 | BigEndian bigEndian 20 | //DefaultEndian is LittleEndian 21 | DefaultEndian = LittleEndian 22 | ) 23 | 24 | type littleEndian struct{} 25 | 26 | func (littleEndian) Uint16(b []byte) uint16 { 27 | _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 28 | return uint16(b[0]) | uint16(b[1])<<8 29 | } 30 | 31 | func (littleEndian) PutUint16(b []byte, v uint16) { 32 | _ = b[1] // early bounds check to guarantee safety of writes below 33 | b[0] = byte(v) 34 | b[1] = byte(v >> 8) 35 | } 36 | 37 | func (littleEndian) Uint32(b []byte) uint32 { 38 | _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 39 | return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 40 | } 41 | 42 | func (littleEndian) PutUint32(b []byte, v uint32) { 43 | _ = b[3] // early bounds check to guarantee safety of writes below 44 | b[0] = byte(v) 45 | b[1] = byte(v >> 8) 46 | b[2] = byte(v >> 16) 47 | b[3] = byte(v >> 24) 48 | } 49 | 50 | func (littleEndian) Uint64(b []byte) uint64 { 51 | _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 52 | return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | 53 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 54 | } 55 | 56 | func (littleEndian) PutUint64(b []byte, v uint64) { 57 | _ = b[7] // early bounds check to guarantee safety of writes below 58 | b[0] = byte(v) 59 | b[1] = byte(v >> 8) 60 | b[2] = byte(v >> 16) 61 | b[3] = byte(v >> 24) 62 | b[4] = byte(v >> 32) 63 | b[5] = byte(v >> 40) 64 | b[6] = byte(v >> 48) 65 | b[7] = byte(v >> 56) 66 | } 67 | 68 | func (littleEndian) String() string { return "LittleEndian" } 69 | 70 | func (littleEndian) GoString() string { return "binary.LittleEndian" } 71 | 72 | type bigEndian struct{} 73 | 74 | func (bigEndian) Uint16(b []byte) uint16 { 75 | _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 76 | return uint16(b[1]) | uint16(b[0])<<8 77 | } 78 | 79 | func (bigEndian) PutUint16(b []byte, v uint16) { 80 | _ = b[1] // early bounds check to guarantee safety of writes below 81 | b[0] = byte(v >> 8) 82 | b[1] = byte(v) 83 | } 84 | 85 | func (bigEndian) Uint32(b []byte) uint32 { 86 | _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 87 | return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 88 | } 89 | 90 | func (bigEndian) PutUint32(b []byte, v uint32) { 91 | _ = b[3] // early bounds check to guarantee safety of writes below 92 | b[0] = byte(v >> 24) 93 | b[1] = byte(v >> 16) 94 | b[2] = byte(v >> 8) 95 | b[3] = byte(v) 96 | } 97 | 98 | func (bigEndian) Uint64(b []byte) uint64 { 99 | _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 100 | return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 101 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 102 | } 103 | 104 | func (bigEndian) PutUint64(b []byte, v uint64) { 105 | _ = b[7] // early bounds check to guarantee safety of writes below 106 | b[0] = byte(v >> 56) 107 | b[1] = byte(v >> 48) 108 | b[2] = byte(v >> 40) 109 | b[3] = byte(v >> 32) 110 | b[4] = byte(v >> 24) 111 | b[5] = byte(v >> 16) 112 | b[6] = byte(v >> 8) 113 | b[7] = byte(v) 114 | } 115 | 116 | func (bigEndian) String() string { return "BigEndian" } 117 | 118 | func (bigEndian) GoString() string { return "binary.BigEndian" } 119 | -------------------------------------------------------------------------------- /example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binary_test 6 | 7 | import ( 8 | "bytes" 9 | "encoding/gob" 10 | "fmt" 11 | "math" 12 | 13 | std "encoding/binary" 14 | 15 | "github.com/vipally/binary" 16 | ) 17 | 18 | func ExampleWrite() { 19 | buf := new(bytes.Buffer) 20 | var pi float64 = math.Pi 21 | err := binary.Write(buf, binary.LittleEndian, pi) 22 | if err != nil { 23 | fmt.Println("binary.Write failed:", err) 24 | } 25 | fmt.Printf("%#v", buf.Bytes()) 26 | 27 | // Output: 28 | // []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x9, 0x40} 29 | } 30 | 31 | func ExampleWrite_multi() { 32 | buf := new(bytes.Buffer) 33 | var data = []interface{}{ 34 | uint16(61374), 35 | int8(-54), 36 | uint8(254), 37 | } 38 | for _, v := range data { 39 | err := binary.Write(buf, binary.LittleEndian, v) 40 | if err != nil { 41 | fmt.Println("binary.Write failed:", err) 42 | } 43 | } 44 | fmt.Printf("%#v", buf.Bytes()) 45 | 46 | // Output: 47 | // []byte{0xbe, 0xef, 0xca, 0xfe} 48 | } 49 | 50 | func ExampleRead() { 51 | var pi float64 52 | b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40} 53 | buf := bytes.NewReader(b) 54 | err := binary.Read(buf, binary.LittleEndian, &pi) 55 | if err != nil { 56 | fmt.Println("binary.Read failed:", err) 57 | } 58 | fmt.Print(pi) 59 | 60 | // Output: 61 | // 3.141592653589793 62 | } 63 | 64 | func ExampleEncode() { 65 | var data struct { 66 | A uint32 67 | B int 68 | C string 69 | } 70 | data.A = 0x11223344 71 | data.B = -5 72 | data.C = "hello" 73 | 74 | b, err := binary.Encode(data, nil) 75 | if err != nil { 76 | fmt.Println("binary.Encode failed:", err) 77 | } 78 | fmt.Printf("Encode:\n%+v\n%#v", data, b) 79 | 80 | // Output: 81 | // Encode: 82 | // {A:287454020 B:-5 C:hello} 83 | // []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 84 | } 85 | func ExampleEncode_withbuffer() { 86 | var data struct { 87 | A uint32 88 | B int 89 | C string 90 | } 91 | data.A = 0x11223344 92 | data.B = -5 93 | data.C = "hello" 94 | size := binary.Sizeof(data) 95 | buffer := make([]byte, size) 96 | 97 | b, err := binary.Encode(data, buffer) 98 | if err != nil { 99 | fmt.Println("binary.Encode failed:", err) 100 | } 101 | fmt.Printf("Encode:\n%+v\n%#v", data, b) 102 | 103 | // Output: 104 | // Encode: 105 | // {A:287454020 B:-5 C:hello} 106 | // []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 107 | } 108 | func ExampleEncode_bools() { 109 | type boolset struct { 110 | A uint8 //0xa 111 | B bool //true 112 | C uint8 //0xc 113 | D []bool //[]bool{true, false, true} 114 | E bool //true 115 | F *uint32 //false 116 | G bool //true 117 | H uint8 //0x8 118 | } 119 | var data = boolset{ 120 | 0xa, true, 0xc, []bool{true, false, true}, true, nil, true, 0x8, 121 | } 122 | b, err := binary.Encode(data, nil) 123 | if err != nil { 124 | fmt.Println(err) 125 | } 126 | 127 | if size := binary.Sizeof(data); size != len(b) { 128 | fmt.Printf("Encode got %#v %+v\nneed %+v\n", len(b), b, size) 129 | } 130 | fmt.Printf("Encode bools:\n%+v\nsize=%d result=%#v", data, len(b), b) 131 | 132 | // Output: 133 | // Encode bools: 134 | // {A:10 B:true C:12 D:[true false true] E:true F: G:true H:8} 135 | // size=6 result=[]byte{0xa, 0xb, 0xc, 0x3, 0x5, 0x8} 136 | } 137 | 138 | func ExampleEncode_boolArray() { 139 | var data = []bool{true, true, true, false, true, true, false, false, true} 140 | b, err := binary.Encode(data, nil) 141 | if err != nil { 142 | fmt.Println(err) 143 | } 144 | 145 | if size := binary.Sizeof(data); size != len(b) { 146 | fmt.Printf("Encode bool array:\ngot %#v %+v\nneed %+v\n", len(b), b, size) 147 | } 148 | fmt.Printf("Encode bool array:\n%#v\nsize=%d result=%#v", data, len(b), b) 149 | 150 | // Output: 151 | // Encode bool array: 152 | // []bool{true, true, true, false, true, true, false, false, true} 153 | // size=3 result=[]byte{0x9, 0x37, 0x1} 154 | } 155 | 156 | func ExampleEncode_packedInts() { 157 | type regedPackedInts struct { 158 | A int16 `binary:"packed"` 159 | B int32 `binary:"packed"` 160 | C int64 `binary:"packed"` 161 | D uint16 `binary:"packed"` 162 | E uint32 `binary:"packed"` 163 | F uint64 `binary:"packed"` 164 | G []uint64 `binary:"packed"` 165 | H uint `binary:"ignore"` 166 | } 167 | binary.RegStruct((*regedPackedInts)(nil)) 168 | 169 | var data = regedPackedInts{1, 2, 3, 4, 5, 6, []uint64{7, 8, 9}, 10} 170 | b, err := binary.Encode(data, nil) 171 | if err != nil { 172 | fmt.Println(err) 173 | } 174 | 175 | if size := binary.Sizeof(data); size != len(b) { 176 | fmt.Printf("PackedInts got %+v %+v\nneed %+v\n", len(b), b, size) 177 | } 178 | 179 | fmt.Printf("Encode packed ints:\n%+v\nsize=%d result=%#v", data, len(b), b) 180 | 181 | // Output: 182 | // Encode packed ints: 183 | // {A:1 B:2 C:3 D:4 E:5 F:6 G:[7 8 9] H:10} 184 | // size=10 result=[]byte{0x2, 0x4, 0x6, 0x4, 0x5, 0x6, 0x3, 0x7, 0x8, 0x9} 185 | } 186 | 187 | func ExampleDecode() { 188 | var s struct { 189 | A uint32 190 | B int 191 | C string 192 | } 193 | buffer := []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 194 | 195 | err := binary.Decode(buffer, &s) 196 | if err != nil { 197 | fmt.Println("binary.Decode failed:", err) 198 | } 199 | fmt.Printf("%+v", s) 200 | 201 | // Output: 202 | // {A:287454020 B:-5 C:hello} 203 | } 204 | func ExampleEncoder() { 205 | encoder := binary.NewEncoder(100) 206 | 207 | encoder.Uint32(0x11223344, false) 208 | encoder.Varint(-5) 209 | encoder.String("hello") 210 | encodeResult := encoder.Buffer() 211 | fmt.Printf("%#v", encodeResult) 212 | 213 | // Output: 214 | // []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 215 | } 216 | func ExampleDecoder() { 217 | buffer := []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 218 | 219 | decoder := binary.NewDecoder(buffer) 220 | u32 := decoder.Uint32(false) 221 | i, _ := decoder.Varint() 222 | str := decoder.String() 223 | fmt.Printf("%#v %#v %#v", u32, i, str) 224 | 225 | // Output: 226 | // 0x11223344 -5 "hello" 227 | } 228 | 229 | type S struct { 230 | A uint32 231 | B int 232 | C string 233 | } 234 | 235 | func (this *S) Size() int { 236 | size := binary.Sizeof(this.A) + binary.Sizeof(this.C) + binary.Sizeof(int16(this.B)) 237 | return size 238 | } 239 | func (this *S) Encode(buffer []byte) ([]byte, error) { 240 | buff, err := binary.MakeEncodeBuffer(this, buffer) 241 | if err != nil { 242 | return nil, err 243 | } 244 | encoder := binary.NewEncoderBuffer(buff) 245 | encoder.Value(this.A) 246 | encoder.Int16(int16(this.B), false) 247 | encoder.Value(this.C) 248 | return encoder.Buffer(), nil 249 | } 250 | func (this *S) Decode(buffer []byte) error { 251 | decoder := binary.NewDecoder(buffer) 252 | decoder.Value(&this.A) 253 | this.B = int(decoder.Int16(false)) 254 | decoder.Value(&this.C) 255 | return nil 256 | } 257 | func ExampleBinarySerializer() { 258 | /* 259 | type S struct { 260 | A uint32 261 | B int 262 | C string 263 | } 264 | func (this *S) Size() int { 265 | size := binary.Sizeof(this.A) + binary.Sizeof(this.C) + binary.Sizeof(int16(this.B)) 266 | return size 267 | } 268 | func (this *S) Encode() ([]byte, error) { 269 | encoder := binary.NewEncoder(this.Size()) 270 | encoder.Value(this.A) 271 | encoder.Int16(int16(this.B), false) 272 | encoder.Value(this.C) 273 | return encoder.Buffer(), nil 274 | } 275 | func (this *S) Decode(buffer []byte) error { 276 | decoder := binary.NewDecoder(buffer) 277 | decoder.Value(&this.A) 278 | this.B = int(decoder.Int16(false)) 279 | decoder.Value(&this.C) 280 | return nil 281 | } 282 | */ 283 | var data, dataDecode S 284 | data.A = 0x11223344 285 | data.B = -5 286 | data.C = "hello" 287 | 288 | b, err := binary.Encode(&data, nil) 289 | if err != nil { 290 | fmt.Println("binary.Encode failed:", err) 291 | } 292 | 293 | err = binary.Decode(b, &dataDecode) 294 | if err != nil { 295 | fmt.Println("binary.Decode failed:", err) 296 | } 297 | fmt.Printf("%+v\n%#v\n%+v", data, b, dataDecode) 298 | 299 | // Output: 300 | // {A:287454020 B:-5 C:hello} 301 | // []byte{0x44, 0x33, 0x22, 0x11, 0xfb, 0xff, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} 302 | // {A:287454020 B:-5 C:hello} 303 | } 304 | 305 | func ExampleSizeof() { 306 | var s struct { 307 | Int8 int8 308 | Int16 int16 309 | Int32 int32 310 | Int64 int64 311 | Uint8 uint8 312 | Uint16 uint16 313 | Uint32 uint32 314 | Uint64 uint64 315 | Float32 float32 316 | Float64 float64 317 | Complex64 complex64 318 | Complex128 complex128 319 | Array [10]uint8 320 | Bool bool 321 | BoolArray [100]bool 322 | Uint32Array [10]uint32 323 | } 324 | 325 | buf := bytes.NewBuffer(make([]byte, 0, 1024)) 326 | coder := gob.NewEncoder(buf) 327 | coder.Encode(s) 328 | gobSize := len(buf.Bytes()) 329 | 330 | stdSize := std.Size(s) 331 | size := binary.Sizeof(s) 332 | 333 | fmt.Printf("Sizeof(s) = %d\nstd Size(s)= %d\ngob Size(s)= %d", size, stdSize, gobSize) 334 | 335 | // Output: 336 | // Sizeof(s) = 133 337 | // std Size(s)= 217 338 | // gob Size(s)= 412 339 | } 340 | 341 | func ExampleRegStruct() { 342 | type someRegedStruct struct { 343 | A int `binary:"ignore"` 344 | B uint64 `binary:"packed"` 345 | C string 346 | D uint 347 | } 348 | binary.RegStruct((*someRegedStruct)(nil)) 349 | 350 | var data = someRegedStruct{1, 2, "hello", 3} 351 | b, err := binary.Encode(data, nil) 352 | if err != nil { 353 | fmt.Println(err) 354 | } 355 | 356 | if size := binary.Sizeof(data); size != len(b) { 357 | fmt.Printf("RegedStruct got %+v %+v\nneed %+v\n", len(b), b, size) 358 | } 359 | 360 | fmt.Printf("Encode reged struct:\n%+v\nsize=%d result=%#v", data, len(b), b) 361 | 362 | // Output: 363 | // Encode reged struct: 364 | // {A:1 B:2 C:hello D:3} 365 | // size=8 result=[]byte{0x2, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x3} 366 | } 367 | -------------------------------------------------------------------------------- /export.go: -------------------------------------------------------------------------------- 1 | // Package binary implements simple translation between numbers and byte 2 | // sequences and encoding and decoding of varints. 3 | // 4 | // Numbers are translated by reading and writing fixed-size values. 5 | // A fixed-size value is either a fixed-size arithmetic 6 | // type (bool, int8, uint8, int16, float32, complex64, ...) 7 | // or an array or struct containing only fixed-size values. 8 | // 9 | // The varint functions encode and decode single integer values using 10 | // a variable-length encoding; smaller values require fewer bytes. 11 | // For a specification, see 12 | // https://developers.google.com/protocol-buffers/docs/encoding. 13 | // 14 | // This package favors simplicity over efficiency. Clients that require 15 | // high-performance serialization, especially for large data structures, 16 | // should look at more advanced solutions such as the encoding/gob 17 | // package or protocol buffers. 18 | // 19 | 20 | // 21 | // Package binary is uesed to Encode/Decode between go data and byte slice. 22 | // 23 | // The main purpose of this package is to replace package "std.binary". 24 | // The design goal is to take both advantages of std.binary(encoding/binary) and gob. 25 | // 26 | // Upgraded from std.binary(encoding/binary). 27 | // 28 | // Compare with other serialization package, this package is with full-feature as 29 | // gob and protocol buffers, and with high-performance and lightweight as std.binary. 30 | // It is designed as a common solution to easily encode/decode between go data and byte slice. 31 | // It is recommended to use in net protocol serialization and go memory data serialization such as DB. 32 | // 33 | // Support all serialize-able data types: 34 | // 35 | // int, int8, int16, int32, int64, 36 | // uint, uint8, uint16, uint32, uint64, 37 | // float32, float64, complex64, complex128, 38 | // bool, string, slice, array, map, struct. 39 | // int/uint will be encoded as varint(1~10 bytes). 40 | // And their direct pointers. 41 | // eg: *string, *struct, *map, *slice, *int32. 42 | // 43 | // Here is the main feature of this package. 44 | // 1. as light-weight as std.binary 45 | // 2. with full-type support like gob. 46 | // 3. as high-performance as std.binary and gob. 47 | // 4. encoding with fewer bytes than std.binary and gob. 48 | // 5. use RegStruct to improve performance of struct encoding/decoding 49 | // 6. recommended using in net protocol serialization and DB serialization 50 | // 51 | // Under MIT license. 52 | // 53 | // Copyright (c) 2017 Ally Dale 54 | // Author : Ally Dale 55 | // Site : https://github.com/vipally 56 | // Origin : https://github.com/vipally/binary 57 | package binary 58 | 59 | import ( 60 | "errors" 61 | "io" 62 | "reflect" 63 | ) 64 | 65 | // Size is same to Sizeof. 66 | // Size returns how many bytes Write would generate to encode the value v, which 67 | // must be a serialize-able value or a slice/map of serialize-able values, or a pointer to such data. 68 | // If v is neither of these, Size returns -1. 69 | func Size(data interface{}) int { 70 | return Sizeof(data) 71 | } 72 | 73 | // Sizeof returns how many bytes Write would generate to encode the value v, which 74 | // must be a serialize-able value or a slice/map/struct of serialize-able values, or a pointer to such data. 75 | // If v is neither of these, Size returns -1. 76 | // If data implements interface BinarySizer, it will use data.Size first. 77 | // It will panic if data implements interface BinarySizer or BinaryEncoder only. 78 | func Sizeof(data interface{}) int { 79 | if p, ok := data.(BinarySizer); ok { 80 | if _, _ok := data.(BinaryEncoder); !_ok { //interface verification 81 | panic(errors.New("expect but not BinaryEncoder:" + reflect.TypeOf(data).String())) 82 | } 83 | return p.Size() 84 | } 85 | 86 | if _, _ok := data.(BinaryEncoder); _ok { //interface verification 87 | panic(errors.New("unexpected BinaryEncoder:" + reflect.TypeOf(data).String())) 88 | } 89 | 90 | return sizeof(data) 91 | } 92 | 93 | // Read reads structured binary data from r into data. 94 | // Data must be a pointer to a fixed-size value or a slice 95 | // of fixed-size values. 96 | // Bytes read from r are decoded using the specified byte order 97 | // and written to successive fields of the data. 98 | // When decoding boolean values, a zero byte is decoded as false, and 99 | // any other non-zero byte is decoded as true. 100 | // When reading into structs, the field data for fields with 101 | // blank (_) field names is skipped; i.e., blank field names 102 | // may be used for padding. 103 | // When reading into a struct, all non-blank fields must be exported. 104 | // 105 | // The error is EOF only if no bytes were read. 106 | // If an EOF happens after reading some but not all the bytes, 107 | // Read returns ErrUnexpectedEOF. 108 | func Read(r io.Reader, endian Endian, data interface{}) error { 109 | var decoder Decoder 110 | decoder.Init(nil, endian) 111 | decoder.reader = r 112 | return decoder.Value(data) 113 | } 114 | 115 | // Write writes the binary representation of data into w. 116 | // Data must be a fixed-size value or a slice of fixed-size 117 | // values, or a pointer to such data. 118 | // Boolean values encode as one byte: 1 for true, and 0 for false. 119 | // Bytes written to w are encoded using the specified byte order 120 | // and read from successive fields of the data. 121 | // When writing structs, zero values are written for fields 122 | // with blank (_) field names. 123 | func Write(w io.Writer, endian Endian, data interface{}) error { 124 | size := Sizeof(data) 125 | if size < 0 { 126 | return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String()) 127 | } 128 | var b [16]byte 129 | var bs []byte 130 | if size > len(b) { 131 | bs = make([]byte, size) 132 | } else { 133 | bs = b[:size] 134 | } 135 | 136 | var encoder Encoder 137 | encoder.buff = bs 138 | encoder.setEndian(endian) 139 | encoder.pos = 0 140 | 141 | err := encoder.Value(data) 142 | assert(err == nil, err) //Value will never return error, because Sizeof(data) < 0 has blocked the error data 143 | 144 | _, err = w.Write(encoder.Buffer()) 145 | return err 146 | } 147 | 148 | // BinarySizer is an interface to define go data Size method. 149 | type BinarySizer interface { 150 | Size() int 151 | } 152 | 153 | // BinaryEncoder is an interface to define go data Encode method. 154 | // buffer is nil-able. 155 | type BinaryEncoder interface { 156 | Encode(buffer []byte) ([]byte, error) 157 | } 158 | 159 | // BinaryDecoder is an interface to define go data Decode method. 160 | type BinaryDecoder interface { 161 | Decode(buffer []byte) error 162 | } 163 | 164 | // BinarySerializer defines the go data Size/Encode/Decode method 165 | type BinarySerializer interface { 166 | BinarySizer 167 | BinaryEncoder 168 | BinaryDecoder 169 | } 170 | 171 | // Encode marshal go data to byte array. 172 | // nil buffer is aviable, it will create new buffer if necessary. 173 | func Encode(data interface{}, buffer []byte) ([]byte, error) { 174 | buff, err := MakeEncodeBuffer(data, buffer) 175 | if err != nil { 176 | return nil, err 177 | } 178 | 179 | encoder := NewEncoderBuffer(buff) 180 | 181 | err = encoder.Value(data) 182 | return encoder.Buffer(), err 183 | } 184 | 185 | // Decode unmarshal go data from byte array. 186 | // data must be interface of pointer for modify. 187 | // It will make new pointer or slice/map for nil-field of data. 188 | func Decode(buffer []byte, data interface{}) error { 189 | var decoder Decoder 190 | decoder.Init(buffer, DefaultEndian) 191 | return decoder.Value(data) 192 | } 193 | 194 | // MakeEncodeBuffer create enough buffer to encode data. 195 | // nil buffer is aviable, it will create new buffer if necessary. 196 | func MakeEncodeBuffer(data interface{}, buffer []byte) ([]byte, error) { 197 | size := Sizeof(data) 198 | if size < 0 { 199 | return nil, errors.New("binary.MakeEncodeBuffer: invalid type " + reflect.TypeOf(data).String()) 200 | } 201 | 202 | buff := buffer 203 | if len(buff) < size { 204 | buff = make([]byte, size) 205 | } 206 | return buff, nil 207 | } 208 | -------------------------------------------------------------------------------- /func.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "unicode" 7 | "unicode/utf8" 8 | ) 9 | 10 | //var ( 11 | // tSizer reflect.Type 12 | // tPacker reflect.Type 13 | // tUnpacker reflect.Type 14 | // tPackUnpacker reflect.Type 15 | //) 16 | 17 | //func init() { 18 | // var sizer Sizer 19 | // var packer Packer 20 | // var unpacker Unpacker 21 | // var packUnpacker PackUnpacker 22 | // tSizer = reflect.TypeOf(&sizer).Elem() 23 | // tPacker = reflect.TypeOf(&packer).Elem() 24 | // tUnpacker = reflect.TypeOf(&unpacker).Elem() 25 | // tPackUnpacker = reflect.TypeOf(&packUnpacker).Elem() 26 | //} 27 | 28 | func sizeof(data interface{}) int { 29 | if s := fastSizeof(data); s >= 0 { 30 | return s 31 | } 32 | 33 | s := bitsOfValue(reflect.ValueOf(data), true, false) 34 | if s < 0 { 35 | return -1 36 | } 37 | return (s + 7) / 8 38 | } 39 | 40 | func fastSizeof(data interface{}) int { 41 | switch d := data.(type) { //fast size calculation 42 | case bool, int8, uint8, *bool, *int8, *uint8: 43 | return 1 44 | case int16, uint16, *int16, *uint16: 45 | return 2 46 | case int32, uint32, *int32, *uint32, float32, *float32: 47 | return 4 48 | case int64, uint64, *int64, *uint64, float64, *float64, complex64, *complex64: 49 | return 8 50 | case complex128, *complex128: 51 | return 16 52 | case string: 53 | return sizeofString(len(d)) 54 | 55 | case int: 56 | return SizeofVarint(int64(d)) 57 | case uint: 58 | return SizeofUvarint(uint64(d)) 59 | case *int: 60 | if d != nil { 61 | return SizeofVarint(int64(*d)) 62 | } 63 | case *uint: 64 | if d != nil { 65 | return SizeofUvarint(uint64(*d)) 66 | } 67 | case []bool: 68 | return sizeofBoolArray(len(d)) 69 | case []int8: 70 | return sizeofFixArray(len(d), 1) 71 | case []uint8: 72 | return sizeofFixArray(len(d), 1) 73 | case []int16: 74 | return sizeofFixArray(len(d), 2) 75 | case []uint16: 76 | return sizeofFixArray(len(d), 2) 77 | case []int32: 78 | return sizeofFixArray(len(d), 4) 79 | case []uint32: 80 | return sizeofFixArray(len(d), 4) 81 | case []float32: 82 | return sizeofFixArray(len(d), 4) 83 | case []int64: 84 | return sizeofFixArray(len(d), 8) 85 | case []uint64: 86 | return sizeofFixArray(len(d), 8) 87 | case []float64: 88 | return sizeofFixArray(len(d), 8) 89 | case []complex64: 90 | return sizeofFixArray(len(d), 8) 91 | case []complex128: 92 | return sizeofFixArray(len(d), 16) 93 | case []string: 94 | l := len(d) 95 | s := SizeofUvarint(uint64(l)) 96 | for _, v := range d { 97 | s += sizeofString(len(v)) 98 | } 99 | return s 100 | case []int: 101 | l := len(d) 102 | s := SizeofUvarint(uint64(l)) 103 | for _, v := range d { 104 | s += SizeofVarint(int64(v)) 105 | } 106 | return s 107 | case []uint: 108 | l := len(d) 109 | s := SizeofUvarint(uint64(l)) 110 | for _, v := range d { 111 | s += SizeofUvarint(uint64(v)) 112 | } 113 | return s 114 | 115 | case *[]bool: 116 | if d != nil { 117 | return fastSizeof(*d) 118 | } 119 | case *[]int8: 120 | if d != nil { 121 | return fastSizeof(*d) 122 | } 123 | case *[]uint8: 124 | if d != nil { 125 | return fastSizeof(*d) 126 | } 127 | case *[]int16: 128 | if d != nil { 129 | return fastSizeof(*d) 130 | } 131 | case *[]uint16: 132 | if d != nil { 133 | return fastSizeof(*d) 134 | } 135 | case *[]int32: 136 | if d != nil { 137 | return fastSizeof(*d) 138 | } 139 | case *[]uint32: 140 | if d != nil { 141 | return fastSizeof(*d) 142 | } 143 | case *[]float32: 144 | if d != nil { 145 | return fastSizeof(*d) 146 | } 147 | case *[]int64: 148 | if d != nil { 149 | return fastSizeof(*d) 150 | } 151 | case *[]uint64: 152 | if d != nil { 153 | return fastSizeof(*d) 154 | } 155 | case *[]float64: 156 | if d != nil { 157 | return fastSizeof(*d) 158 | } 159 | case *[]complex64: 160 | if d != nil { 161 | return fastSizeof(*d) 162 | } 163 | case *[]complex128: 164 | if d != nil { 165 | return fastSizeof(*d) 166 | } 167 | case *[]string: 168 | if d != nil { 169 | return fastSizeof(*d) 170 | } 171 | case *[]int: 172 | if d != nil { 173 | return fastSizeof(*d) 174 | } 175 | case *[]uint: 176 | if d != nil { 177 | return fastSizeof(*d) 178 | } 179 | } 180 | return -1 181 | } 182 | 183 | func assert(b bool, msg interface{}) { 184 | if !b { 185 | panic(fmt.Errorf("%s", msg)) 186 | } 187 | } 188 | 189 | func bitsOfUnfixedArray(v reflect.Value, packed bool) int { 190 | if !validUserType(v.Type().Elem()) { //check if array element type valid 191 | return -1 192 | } 193 | 194 | arrayLen := v.Len() 195 | sum := SizeofUvarint(uint64(arrayLen)) * 8 //array size bytes num 196 | for i, n := 0, arrayLen; i < n; i++ { 197 | s := bitsOfValue(v.Index(i), false, packed) 198 | //assert(s >= 0, v.Type().String()) //element size must not error 199 | sum += s 200 | } 201 | return sum 202 | } 203 | 204 | // sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. 205 | func bitsOfValue(v reflect.Value, topLevel bool, packed bool) (r int) { 206 | // defer func() { 207 | // fmt.Printf("bitsOfValue(%#v)=%d\n", v.Interface(), r) 208 | // }() 209 | bits := 0 210 | if v.Kind() == reflect.Ptr { //nil is not aviable 211 | if !topLevel { 212 | bits = 1 213 | } 214 | if v.IsNil() { 215 | if topLevel || !validUserType(v.Type()) { 216 | return -1 217 | } 218 | return 1 219 | } 220 | } 221 | 222 | v = reflect.Indirect(v) //redrect pointer to it's value 223 | t := v.Type() 224 | if s := fixedTypeSize(t); s > 0 { //fixed size 225 | if packedType := packedIntsType(t); packedType > 0 && packed { 226 | switch packedType { 227 | case _SignedInts: 228 | return SizeofVarint(v.Int())*8 + bits 229 | case _UnsignedInts: 230 | return SizeofUvarint(v.Uint())*8 + bits 231 | } 232 | } else { 233 | return s*8 + bits 234 | } 235 | } 236 | switch t := v.Type(); t.Kind() { 237 | case reflect.Bool: 238 | return 1 + bits 239 | case reflect.Int: 240 | return SizeofVarint(v.Int())*8 + bits 241 | case reflect.Uint: 242 | return SizeofUvarint(v.Uint())*8 + bits 243 | case reflect.Slice, reflect.Array: 244 | arrayLen := v.Len() 245 | elemtype := t.Elem() 246 | if s := fixedTypeSize(elemtype); s > 0 { 247 | if packedIntsType(elemtype) > 0 && packed { 248 | return bitsOfUnfixedArray(v, packed) + bits 249 | } 250 | 251 | return sizeofFixArray(arrayLen, s)*8 + bits 252 | } 253 | 254 | if elemtype.Kind() == reflect.Bool { 255 | return sizeofBoolArray(arrayLen)*8 + bits 256 | } 257 | return bitsOfUnfixedArray(v, packed) + bits 258 | case reflect.Map: 259 | mapLen := v.Len() 260 | sum := SizeofUvarint(uint64(mapLen))*8 + bits //array size 261 | keys := v.MapKeys() 262 | 263 | if !validUserType(t.Key()) || 264 | !validUserType(t.Elem()) { //check if map key and value type valid 265 | return -1 266 | } 267 | 268 | for i := 0; i < mapLen; i++ { 269 | key := keys[i] 270 | sizeKey := bitsOfValue(key, false, packed) 271 | //assert(sizeKey >= 0, key.Type().Kind().String()) //key size must not error 272 | 273 | sum += sizeKey 274 | value := v.MapIndex(key) 275 | sizeValue := bitsOfValue(value, false, packed) 276 | //assert(sizeValue >= 0, value.Type().Kind().String()) //key size must not error 277 | 278 | sum += sizeValue 279 | } 280 | return sum 281 | 282 | case reflect.Struct: 283 | return queryStruct(v.Type()).bitsOfValue(v) + bits 284 | 285 | case reflect.String: 286 | return sizeofString(v.Len())*8 + bits //string length and data 287 | } 288 | return -1 289 | } 290 | 291 | //BUG: 292 | // bool as a byte, but not bit 293 | // always use this functin to verify if Type is valid 294 | // and do not care the value of return bytes 295 | func sizeofNilPointer(t reflect.Type) int { 296 | tt := t 297 | if tt.Kind() == reflect.Ptr { 298 | tt = t.Elem() 299 | } 300 | if s := fixedTypeSize(tt); s > 0 { //fix size 301 | return s 302 | } 303 | switch tt.Kind() { 304 | case reflect.Bool: 305 | return 1 306 | case reflect.Int, reflect.Uint: //zero varint will be encoded as 1 byte 307 | return 1 308 | case reflect.String: 309 | return SizeofUvarint(0) 310 | case reflect.Slice: 311 | if validUserType(tt.Elem()) { //verify element type valid 312 | return SizeofUvarint(0) 313 | } 314 | case reflect.Map: 315 | if validUserType(tt.Key()) && 316 | validUserType(tt.Elem()) { //verify key and value type valid 317 | return SizeofUvarint(0) 318 | } 319 | case reflect.Array: 320 | elemtype := tt.Elem() 321 | if s := fixedTypeSize(elemtype); s > 0 { 322 | return sizeofFixArray(tt.Len(), s) 323 | } 324 | 325 | if elemtype.Kind() == reflect.Bool { 326 | return sizeofBoolArray(tt.Len()) 327 | } 328 | size := sizeofNilPointer(elemtype) 329 | if size > 0 { //verify element type valid 330 | return sizeofFixArray(tt.Len(), size) 331 | } 332 | case reflect.Struct: 333 | return queryStruct(tt).sizeofNilPointer(tt) 334 | } 335 | 336 | return -1 337 | } 338 | 339 | const ( 340 | _SignedInts = iota + 1 341 | _UnsignedInts 342 | ) 343 | 344 | func packedIntsType(t reflect.Type) int { 345 | switch t.Kind() { 346 | case reflect.Int16, reflect.Int32, reflect.Int64: 347 | return _SignedInts 348 | case reflect.Uint16, reflect.Uint32, reflect.Uint64: 349 | return _UnsignedInts 350 | } 351 | return 0 352 | } 353 | 354 | func fixedTypeSize(t reflect.Type) int { 355 | switch t.Kind() { 356 | case reflect.Int8, reflect.Uint8: 357 | return 1 358 | case reflect.Int16, reflect.Uint16: 359 | return 2 360 | case reflect.Int32, reflect.Uint32, reflect.Float32: 361 | return 4 362 | case reflect.Int64, reflect.Uint64, reflect.Float64, reflect.Complex64: 363 | return 8 364 | case reflect.Complex128: 365 | return 16 366 | } 367 | return -1 368 | } 369 | 370 | // Auto allocate for aviable pointer 371 | func newPtr(v reflect.Value, decoder *Decoder, topLevel bool) bool { 372 | if v.Kind() == reflect.Ptr { 373 | e := v.Type().Elem() 374 | switch e.Kind() { 375 | case reflect.Array, reflect.Struct, reflect.Slice, reflect.Map: 376 | if !validUserType(e) { //check if valid pointer type 377 | return false 378 | } 379 | fallthrough 380 | case reflect.Int, reflect.Uint, reflect.Bool, reflect.Int8, reflect.Uint8, reflect.Int16, 381 | reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, 382 | reflect.Uint64, reflect.Float32, reflect.Float64, reflect.Complex64, 383 | reflect.Complex128, reflect.String: 384 | isNotNilPointer := false 385 | if !topLevel { 386 | isNotNilPointer = decoder.Bool() 387 | if v.IsNil() { 388 | if isNotNilPointer { 389 | v.Set(reflect.New(e)) 390 | } 391 | } 392 | } 393 | return true 394 | } 395 | } 396 | return false 397 | } 398 | 399 | // NOTE: 400 | // This function will make the encode/decode of struct slow down. 401 | // It is recommended to use RegStruct to improve this case. 402 | func validField(f reflect.StructField) bool { 403 | if isExported(f.Name) && f.Tag.Get("binary") != "ignore" { 404 | return true 405 | } 406 | return false 407 | } 408 | 409 | // isExported reports whether the identifier is exported. 410 | func isExported(id string) bool { 411 | r, _ := utf8.DecodeRuneInString(id) 412 | return unicode.IsUpper(r) 413 | } 414 | 415 | //size of bool array when encode 416 | func sizeofBoolArray(_len int) int { 417 | return SizeofUvarint(uint64(_len)) + (_len+8-1)/8 418 | } 419 | 420 | //size of string when encode 421 | func sizeofString(_len int) int { 422 | return SizeofUvarint(uint64(_len)) + _len 423 | } 424 | 425 | //size of fix array, like []int16, []int64 426 | func sizeofFixArray(_len, elemLen int) int { 427 | return SizeofUvarint(uint64(_len)) + _len*elemLen 428 | } 429 | 430 | func validUserType(t reflect.Type) bool { 431 | return sizeofNilPointer(t) >= 0 432 | } 433 | -------------------------------------------------------------------------------- /struct.go: -------------------------------------------------------------------------------- 1 | // cache struct info to improve encoding/decoding efficiency. 2 | 3 | package binary 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | ) 9 | 10 | // RegStruct regist struct info to improve encoding/decoding efficiency. 11 | // Regist by a nil pointer is aviable. 12 | // RegStruct((*someStruct)(nil)) is recommended usage. 13 | func RegStruct(data interface{}) error { 14 | return _structInfoMgr.regist(reflect.TypeOf(data)) 15 | } 16 | 17 | var _structInfoMgr structInfoMgr 18 | 19 | func init() { 20 | _structInfoMgr.init() 21 | } 22 | 23 | type structInfoMgr struct { 24 | reg map[string]*structInfo 25 | } 26 | 27 | func (mgr *structInfoMgr) init() { 28 | mgr.reg = make(map[string]*structInfo) 29 | } 30 | func (mgr *structInfoMgr) regist(t reflect.Type) error { 31 | if _t, _, err := mgr.deepStructType(t, true); err == nil { 32 | if mgr.query(_t) == nil { 33 | p := &structInfo{} 34 | if p.parse(_t) { 35 | mgr.reg[p.identify] = p 36 | } 37 | } else { 38 | return fmt.Errorf("binary: regist duplicate type %s", _t.String()) 39 | } 40 | } else { 41 | return err 42 | } 43 | return nil 44 | } 45 | 46 | func (mgr *structInfoMgr) query(t reflect.Type) *structInfo { 47 | if _t, _ok, _ := mgr.deepStructType(t, false); _ok { 48 | if p, ok := mgr.reg[_t.String()]; ok { 49 | return p 50 | } 51 | } 52 | return nil 53 | } 54 | 55 | func (mgr *structInfoMgr) deepStructType(t reflect.Type, needErr bool) (reflect.Type, bool, error) { 56 | _t := t 57 | for _t.Kind() == reflect.Ptr { 58 | _t = _t.Elem() 59 | } 60 | if _t.Kind() != reflect.Struct { 61 | if needErr { 62 | return _t, false, fmt.Errorf("binary: only struct is aviable for regist, but got %s", t.String()) 63 | } 64 | 65 | return _t, false, nil 66 | } 67 | return _t, true, nil 68 | } 69 | 70 | //informatin of a struct 71 | type structInfo struct { 72 | identify string //reflect.Type.String() 73 | fields []*fieldInfo 74 | } 75 | 76 | func (info *structInfo) encode(encoder *Encoder, v reflect.Value) error { 77 | //assert(v.Kind() == reflect.Struct, v.Type().String()) 78 | t := v.Type() 79 | for i, n := 0, v.NumField(); i < n; i++ { 80 | // see comment for corresponding code in decoder.value() 81 | finfo := info.field(i) 82 | if f := v.Field(i); finfo.isValid(i, t) { 83 | if err := encoder.value(f, finfo.isPacked()); err != nil { 84 | return err 85 | } 86 | } 87 | } 88 | return nil 89 | } 90 | 91 | func (info *structInfo) decode(decoder *Decoder, v reflect.Value) error { 92 | t := v.Type() 93 | //assert(t.Kind() == reflect.Struct, t.String()) 94 | for i, n := 0, v.NumField(); i < n; i++ { 95 | finfo := info.field(i) 96 | if f := v.Field(i); finfo.isValid(i, t) { 97 | if err := decoder.value(f, false, finfo.isPacked()); err != nil { 98 | return err 99 | } 100 | } 101 | } 102 | return nil 103 | } 104 | 105 | func (info *structInfo) decodeSkipByType(decoder *Decoder, t reflect.Type, packed bool) int { 106 | //assert(t.Kind() == reflect.Struct, t.String()) 107 | sum := 0 108 | for i, n := 0, t.NumField(); i < n; i++ { 109 | f := info.field(i) 110 | ft := f.Type(i, t) 111 | s := decoder.skipByType(ft, f.isPacked()) 112 | assert(s >= 0, "skip struct field fail:"+ft.String()) //I'm sure here cannot find unsupported type 113 | sum += s 114 | } 115 | return sum 116 | } 117 | 118 | func (info *structInfo) bitsOfValue(v reflect.Value) int { 119 | t := v.Type() 120 | //assert(t.Kind() == reflect.Struct,t.String()) 121 | sum := 0 122 | for i, n := 0, v.NumField(); i < n; i++ { 123 | 124 | if finfo := info.field(i); finfo.isValid(i, t) { 125 | if s := bitsOfValue(v.Field(i), false, finfo.isPacked()); s >= 0 { 126 | sum += s 127 | } else { 128 | return -1 //invalid field type 129 | } 130 | } 131 | } 132 | return sum 133 | } 134 | 135 | func (info *structInfo) sizeofNilPointer(t reflect.Type) int { 136 | sum := 0 137 | for i, n := 0, info.fieldNum(t); i < n; i++ { 138 | if info.fieldValid(i, t) { 139 | if s := sizeofNilPointer(info.field(i).Type(i, t)); s >= 0 { 140 | sum += s 141 | } else { 142 | return -1 //invalid field type 143 | } 144 | } 145 | } 146 | return sum 147 | } 148 | 149 | //check if field i of t valid for encoding/decoding 150 | func (info *structInfo) fieldValid(i int, t reflect.Type) bool { 151 | return info.field(i).isValid(i, t) 152 | } 153 | 154 | func (info *structInfo) fieldNum(t reflect.Type) int { 155 | if info == nil { 156 | return t.NumField() 157 | } 158 | 159 | return info.numField() 160 | } 161 | 162 | func (info *structInfo) parse(t reflect.Type) bool { 163 | //assert(t.Kind() == reflect.Struct, t.String()) 164 | info.identify = t.String() 165 | for i, n := 0, t.NumField(); i < n; i++ { 166 | f := t.Field(i) 167 | 168 | field := &fieldInfo{} 169 | field.field = f 170 | tag := f.Tag.Get("binary") 171 | field.ignore = !isExported(f.Name) || tag == "ignore" 172 | field.packed = tag == "packed" 173 | 174 | info.fields = append(info.fields, field) 175 | 176 | //deep regist if field is a struct 177 | if _t, ok, _ := _structInfoMgr.deepStructType(f.Type, false); ok { 178 | if err := _structInfoMgr.regist(_t); err != nil { 179 | //fmt.Printf("binary: internal regist duplicate type %s\n", _t.String()) 180 | continue 181 | } 182 | } 183 | } 184 | return true 185 | } 186 | 187 | func (info *structInfo) field(i int) *fieldInfo { 188 | if nil != info && i >= 0 && i < info.numField() { 189 | return info.fields[i] 190 | } 191 | return nil 192 | } 193 | 194 | func (info *structInfo) numField() int { 195 | if nil != info { 196 | return len(info.fields) 197 | } 198 | return 0 199 | } 200 | 201 | //informatin of a struct field 202 | type fieldInfo struct { 203 | field reflect.StructField 204 | ignore bool //if this field is ignored 205 | packed bool //if this ints field encode as varint/uvarint 206 | } 207 | 208 | func (field *fieldInfo) Type(i int, t reflect.Type) reflect.Type { 209 | if field != nil { 210 | return field.field.Type 211 | } 212 | 213 | return t.Field(i).Type 214 | } 215 | 216 | func (field *fieldInfo) isValid(i int, t reflect.Type) bool { 217 | if field != nil { 218 | return !field.ignore 219 | } 220 | 221 | // NOTE: 222 | // creating the StructField info for each field is costly 223 | // use RegStruct((*someStruct)(nil)) to aboid this path 224 | return validField(t.Field(i)) // slow way to access field info 225 | } 226 | 227 | func (field *fieldInfo) isPacked() bool { 228 | return field != nil && field.packed 229 | } 230 | 231 | func queryStruct(t reflect.Type) *structInfo { 232 | return _structInfoMgr.query(t) 233 | } 234 | -------------------------------------------------------------------------------- /varint.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binary 6 | 7 | // This file implements "varint" encoding of 64-bit integers. 8 | // The encoding is: 9 | // - unsigned integers are serialized 7 bits at a time, starting with the 10 | // least significant bits 11 | // - the most significant bit (msb) in each output byte indicates if there 12 | // is a continuation byte (msb = 1) 13 | // - signed integers are mapped to unsigned integers using "zig-zag" 14 | // encoding: Positive values x are written as 2*x + 0, negative values 15 | // are written as 2*(^x) + 1; that is, negative numbers are complemented 16 | // and whether to complement is encoded in bit 0. 17 | // 18 | // Design note: 19 | // At most 10 bytes are needed for 64-bit values. The encoding could 20 | // be more dense: a full 64-bit value needs an extra byte just to hold bit 63. 21 | // Instead, the msb of the previous byte could be used to hold bit 63 since we 22 | // know there can't be more than 64 bits. This is a trivial improvement and 23 | // would reduce the maximum encoding length to 9 bytes. However, it breaks the 24 | // invariant that the msb is always the "continuation bit" and thus makes the 25 | // format incompatible with a varint encoding for larger numbers (say 128-bit). 26 | 27 | import ( 28 | "errors" 29 | "io" 30 | ) 31 | 32 | // MaxVarintLenN is the maximum length of a varint-encoded N-bit integer. 33 | const ( 34 | MaxVarintLen16 = 3 35 | MaxVarintLen32 = 5 36 | MaxVarintLen64 = 10 37 | ) 38 | 39 | // PutUvarint encodes a uint64 into buf and returns the number of bytes written. 40 | // If the buffer is too small, PutUvarint will panic. 41 | func PutUvarint(buf []byte, x uint64) int { 42 | i := 0 43 | for x >= 0x80 { 44 | buf[i] = byte(x) | 0x80 45 | x >>= 7 46 | i++ 47 | } 48 | buf[i] = byte(x) 49 | return i + 1 50 | } 51 | 52 | // Uvarint decodes a uint64 from buf and returns that value and the 53 | // number of bytes read (> 0). If an error occurred, the value is 0 54 | // and the number of bytes n is <= 0 meaning: 55 | // 56 | // n == 0: buf too small 57 | // n < 0: value larger than 64 bits (overflow) 58 | // and -n is the number of bytes read 59 | // 60 | func Uvarint(buf []byte) (uint64, int) { 61 | var x uint64 62 | var s uint 63 | for i, b := range buf { 64 | if b < 0x80 { 65 | if i > 9 || i == 9 && b > 1 { 66 | return 0, -(i + 1) // overflow 67 | } 68 | return x | uint64(b)< 0). If an error occurred, the value is 0 84 | // and the number of bytes n is <= 0 with the following meaning: 85 | // 86 | // n == 0: buf too small 87 | // n < 0: value larger than 64 bits (overflow) 88 | // and -n is the number of bytes read 89 | // 90 | func Varint(buf []byte) (int64, int) { 91 | ux, n := Uvarint(buf) // ok to continue in presence of error 92 | return ToVarint(ux), n 93 | } 94 | 95 | var errOverflow = errors.New("binary: varint overflows a 64-bit integer") 96 | 97 | // ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64. 98 | func ReadUvarint(r io.ByteReader) (uint64, error) { 99 | var x uint64 100 | var s uint 101 | for i := 0; ; i++ { 102 | b, err := r.ReadByte() 103 | if err != nil { 104 | return x, err 105 | } 106 | if b < 0x80 { 107 | if i > 9 || i == 9 && b > 1 { 108 | return x, errOverflow 109 | } 110 | return x | uint64(b)<> 1) //move bit0 to sign bit 140 | if ux&1 != 0 { 141 | x = ^x 142 | } 143 | return x 144 | } 145 | 146 | // SizeofVarint return bytes number of an int64 value store as varint 147 | func SizeofVarint(x int64) int { 148 | return SizeofUvarint(ToUvarint(x)) 149 | } 150 | 151 | // SizeofUvarint return bytes number of an uint64 value store as uvarint 152 | func SizeofUvarint(ux uint64) int { 153 | i := 0 154 | for n := ux; n >= 0x80; n >>= 7 { 155 | i++ 156 | } 157 | return i + 1 158 | } 159 | -------------------------------------------------------------------------------- /varint_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package binary 6 | 7 | import ( 8 | "bytes" 9 | "io" 10 | "testing" 11 | ) 12 | 13 | func testConstant(t *testing.T, w uint, max int) { 14 | buf := make([]byte, MaxVarintLen64) 15 | n := PutUvarint(buf, 1<