diff --git a/README.md b/README.md index 683b85f..ab5e4a2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ -# binary [![Build Status](https://travis-ci.org/vipally/binary.svg?branch=master)](https://travis-ci.org/vipally/binary) [![Coverage Status](https://coveralls.io/repos/github/vipally/binary/badge.svg?branch=master)](https://coveralls.io/github/vipally/binary?branch=master) [![GoDoc](https://godoc.org/github.com/vipally/binary?status.svg)](https://godoc.org/github.com/vipally/binary) ![Version](https://img.shields.io/badge/version-1.0.0.final-green.svg) - Package binary is uesed to Pack/Unpack between go data and byte slice. +# binary + +[![Build Status](https://travis-ci.org/vipally/binary.svg?branch=master)](https://travis-ci.org/vipally/binary) [![Coverage Status](https://coveralls.io/repos/github/vipally/binary/badge.svg?branch=master)](https://coveralls.io/github/vipally/binary?branch=master) [![GoDoc](https://godoc.org/github.com/vipally/binary?status.svg)](https://godoc.org/github.com/vipally/binary) ![Version](https://img.shields.io/badge/version-1.1.0-green.svg) + +*** + + Package binary is uesed to Encode/Decode between go data and byte slice. The main purpose of this package is to replace package "std.binary". @@ -30,7 +35,7 @@ Site : [https://github.com/vipally](https://github.com/vipally) And their direct pointers. eg: *string, *struct, *map, *slice, *int32. -# 2. [recommended usage] Use Pack/UnPack to read/write memory buffer directly. +# 2. [recommended usage] Use Encode/Decode to read/write memory buffer directly. ## Use RegStruct to improve struct encoding/decoding efficiency. type someRegedStruct struct { A int `binary:"ignore"` @@ -39,31 +44,31 @@ Site : [https://github.com/vipally](https://github.com/vipally) } binary.RegStruct((*someRegedStruct)(nil)) - If data implements interface Packer, it will use data.Pack/data.Unpack + If data implements interface BinaryEncoder, it will use data.Encode/data.Decode to encode/decode data. - NOTE that data.Unpack must implement on pointer receiever to enable modifying - receiever.Even though Size/Pack of data can implement on non-pointer receiever, - binary.Pack(&data, nil) is required if data has implement interface Packer. - binary.Pack(data, nil) will probably NEVER use Packer methods to Pack/Unpack + NOTE that data.Decode must implement on pointer receiever to enable modifying + receiever.Even though Size/Encode of data can implement on non-pointer receiever, + binary.Encode(&data, nil) is required if data has implement interface BinaryEncoder. + binary.Encode(data, nil) will probably NEVER use BinaryEncoder methods to Encode/Decode data. eg: import "github.com/vipally/binary" - //1.Pack with default buffer - if bytes, err := binary.Pack(&data, nil); err==nil{ + //1.Encode with default buffer + if bytes, err := binary.Encode(&data, nil); err==nil{ //... } - //2.Pack with existing buffer + //2.Encode with existing buffer size := binary.Sizeof(data) buffer := make([]byte, size) - if bytes, err := binary.Pack(&data, buffer); err==nil{ + if bytes, err := binary.Encode(&data, buffer); err==nil{ //... } - //3.Unpack from buffer - if err := binary.Unpack(bytes, &data); err==nil{ + //3.Decode from buffer + if err := binary.Decode(bytes, &data); err==nil{ //... } diff --git a/bench_test.go b/bench_test.go index e6c0f55..56441d9 100644 --- a/bench_test.go +++ b/bench_test.go @@ -230,7 +230,7 @@ func testBenchPack(b *testing.B, data interface{}, caseName string) { b.SetBytes(int64(Sizeof(data))) b.ResetTimer() for i := 0; i < b.N; i++ { - Pack(data, buff) + Encode(data, buff) } b.StopTimer() } @@ -310,7 +310,7 @@ func testBenchRead(b *testing.B, data, w interface{}, caseName string) { } } func testBenchUnpack(b *testing.B, data, w interface{}, caseName string) { - buf, err := Pack(data, buff) + buf, err := Encode(data, buff) if err != nil { b.Error(caseName, err) } @@ -318,7 +318,7 @@ func testBenchUnpack(b *testing.B, data, w interface{}, caseName string) { b.ResetTimer() for i := 0; i < b.N; i++ { - Unpack(buf, w) + Decode(buf, w) } b.StopTimer() if b.N > 0 && !reflect.DeepEqual(data, w) { diff --git a/coder_test.go b/coder_test.go index f02e64b..2149cac 100644 --- a/coder_test.go +++ b/coder_test.go @@ -336,7 +336,7 @@ func TestPack(t *testing.T) { if !validField(vt.Field(i)) { continue } - b, err := Pack(v.Field(i).Interface(), nil) + b, err := Encode(v.Field(i).Interface(), nil) c := check[:len(b)] check = check[len(b):] if err != nil { @@ -363,7 +363,7 @@ func TestPack(t *testing.T) { func TestUnpack(t *testing.T) { var v fullStruct - err := Unpack(littleFullAll, &v) + err := Decode(littleFullAll, &v) if err != nil { t.Error(err) } @@ -450,18 +450,18 @@ func TestPackEmptyPointer(t *testing.T) { PStruct *struct{ A int } PStruct2 *struct{ B *[]string } } - b, err := Pack(&s, nil) + b, err := Encode(&s, nil) if err != nil { t.Error(err) } ss := s - err = Unpack(b, &ss) + err = Decode(b, &ss) if err != nil { t.Error(err) } - b2, err2 := Pack(&ss, nil) + b2, err2 := Encode(&ss, nil) if err2 != nil { t.Error(err) } @@ -486,7 +486,7 @@ func TestHideStructField(t *testing.T) { s.b = 0x22334455 s.C = 0x33445566 check := []byte{0x44, 0x33, 0x22, 0x11} - b, err := Pack(s, nil) + b, err := Encode(s, nil) if err != nil { t.Error(err) } @@ -495,7 +495,7 @@ func TestHideStructField(t *testing.T) { } var ss, ssCheck T ssCheck.A = s.A - err = Unpack(b, &ss) + err = Decode(b, &ss) if err != nil { t.Error(err) } @@ -577,12 +577,12 @@ func TestDecoderSkip(t *testing.T) { } var r [4]s - b, err := Pack(&w, nil) + b, err := Encode(&w, nil) if err != nil { t.Error(err) } - err2 := Unpack(b, &r) + err2 := Decode(b, &r) if err2 != nil { t.Error(err2) } @@ -625,7 +625,7 @@ func TestFastValue(t *testing.T) { func TestPackDonotSupportedType(t *testing.T) { ts := doNotSupportTypes - if _, err := Pack(ts, nil); err == nil { + if _, err := Encode(ts, nil); err == nil { t.Errorf("PackDonotSupportedType: have err == nil, want non-nil") } @@ -635,7 +635,7 @@ func TestPackDonotSupportedType(t *testing.T) { tv := reflect.Indirect(reflect.ValueOf(&ts)) for i, n := 0, tv.NumField(); i < n; i++ { - if _, err := Pack(tv.Field(i).Interface(), nil); err == nil { + if _, err := Encode(tv.Field(i).Interface(), nil); err == nil { t.Errorf("PackDonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) } else { //fmt.Println(err) @@ -647,7 +647,7 @@ func TestPackDonotSupportedType(t *testing.T) { //fmt.Println(err) } - if err := Unpack(buff, tv.Field(i).Addr().Interface()); err == nil { + if err := Decode(buff, tv.Field(i).Addr().Interface()); err == nil { t.Errorf("Unpack DonotSupportedType.%v: have err == nil, want non-nil", tv.Field(i).Type()) } else { //fmt.Printf("Unpack error: %#v\n%s\n", tv.Field(i).Addr().Type().String(), err.Error()) @@ -726,14 +726,14 @@ func TestRegStruct(t *testing.T) { } a.S.A = 9 a.S.B = "abc" - b, err := Pack(&a, nil) + b, err := Encode(&a, nil) if err != nil { t.Error(err) } var r StructForReg //fmt.Printf("%#v\n%#v\n", a, b) - err = Unpack(b, &r) + err = Decode(b, &r) if err != nil { t.Error(err) } @@ -787,50 +787,50 @@ type sizerOnly struct{ A uint8 } func (this sizerOnly) Size() int { return 1 } -type packerOnly struct{ B uint8 } +type encoderOnly struct{ B uint8 } -func (this packerOnly) Pack(buffer []byte) ([]byte, error) { return nil, nil } +func (this encoderOnly) Encode(buffer []byte) ([]byte, error) { return nil, nil } -type unpackerOnly struct { +type decoderOnly struct { C uint8 } -func (this *unpackerOnly) Unpack(buffer []byte) error { return nil } +func (this *decoderOnly) Decode(buffer []byte) error { return nil } type sizepackerOnly struct { sizerOnly - packerOnly + encoderOnly } type sizeunpackerOnly struct { sizerOnly - unpackerOnly + decoderOnly } type packunpackerOnly struct { - packerOnly - unpackerOnly + encoderOnly + decoderOnly } -type fullPackUnpacker struct { +type fullSerializer struct { sizerOnly - packerOnly - unpackerOnly + encoderOnly + decoderOnly } -type fullPackUnpackerUnpackerror struct { - fullPackUnpacker +type fullSerializerError struct { + fullSerializer } -func (this *fullPackUnpackerUnpackerror) Unpack(buffer []byte) error { +func (this *fullSerializerError) Decode(buffer []byte) error { return fmt.Errorf("expected error") } func TestPackUnpacker(t *testing.T) { var a sizerOnly - var b packerOnly - var c unpackerOnly + var b encoderOnly + var c decoderOnly var d sizepackerOnly var e sizeunpackerOnly var f packunpackerOnly - var g fullPackUnpackerUnpackerror - var h fullPackUnpacker + var g fullSerializerError + var h fullSerializer testCase := func(data interface{}, testcase int) (info interface{}) { defer func() { @@ -845,13 +845,13 @@ func TestPackUnpacker(t *testing.T) { case 1: Sizeof(data) case 2: - if _, err := Pack(data, nil); err != nil { + if _, err := Encode(data, nil); err != nil { info = err } case 3: buff := make([]byte, 1000) - if err := Unpack(buff, data); err != nil { + if err := Decode(buff, data); err != nil { info = err } case 4: diff --git a/decoder.go b/decoder.go index dee607a..5a710a0 100644 --- a/decoder.go +++ b/decoder.go @@ -217,7 +217,7 @@ func (this *Decoder) Uvarint() (uint64, int) { // x must be interface of pointer for modify. // It will return none-nil error if x contains unsupported types // or buffer is not enough. -// It will check if x implements interface Unpacker and use x.Unpack first. +// It will check if x implements interface BinaryEncoder and use x.Encode first. func (this *Decoder) Value(x interface{}) (err error) { defer func() { if info := recover(); info != nil { @@ -234,28 +234,28 @@ func (this *Decoder) Value(x interface{}) (err error) { v := reflect.ValueOf(x) - if p, ok := x.(Unpacker); ok { + if p, ok := x.(BinaryDecoder); ok { size := 0 - if sizer, _ok := x.(Sizer); _ok { //interface verification + if sizer, _ok := x.(BinarySizer); _ok { //interface verification size = sizer.Size() } else { - panic(fmt.Errorf("expect but not Sizer: %s", v.Type().String())) + panic(fmt.Errorf("expect but not BinarySizer: %s", v.Type().String())) } - if _, _ok := x.(Packer); !_ok { //interface verification - panic(fmt.Errorf("unexpect but not Packer: %s", v.Type().String())) + if _, _ok := x.(BinaryEncoder); !_ok { //interface verification + panic(fmt.Errorf("unexpect but not BinaryEncoder: %s", v.Type().String())) } - err := p.Unpack(this.buff[this.pos:]) + err := p.Decode(this.buff[this.pos:]) if err != nil { return err } this.reserve(size) return nil } else { - if _, _ok := x.(Sizer); _ok { //interface verification - panic(fmt.Errorf("unexpected Sizer: %s", v.Type().String())) + if _, _ok := x.(BinarySizer); _ok { //interface verification + panic(fmt.Errorf("unexpected BinarySizer: %s", v.Type().String())) } - if _, _ok := x.(Packer); _ok { //interface verification - panic(fmt.Errorf("unexpected Packer: %s", v.Type().String())) + if _, _ok := x.(BinaryEncoder); _ok { //interface verification + panic(fmt.Errorf("unexpected BinaryEncoder: %s", v.Type().String())) } } @@ -338,7 +338,7 @@ func (this *Decoder) value(v reflect.Value, topLevel bool) error { v.SetString(this.String()) case reflect.Slice, reflect.Array: - if sizeofNilPointer(v.Type().Elem()) < 0 { //verify array element is valid + if !validUserType(v.Type().Elem()) { //verify array element is valid return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) } if this.boolArray(v) < 0 { //deal with bool array first @@ -362,8 +362,8 @@ func (this *Decoder) value(v reflect.Value, topLevel bool) error { t := v.Type() kt := t.Key() vt := t.Elem() - if sizeofNilPointer(kt) < 0 || - sizeofNilPointer(vt) < 0 { //verify map key and value type are both valid + if !validUserType(kt) || + !validUserType(vt) { //verify map key and value type are both valid return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) } diff --git a/encoder.go b/encoder.go index 8d55981..b2c7f17 100644 --- a/encoder.go +++ b/encoder.go @@ -179,7 +179,7 @@ func (this *Encoder) Uvarint(x uint64) int { // Value encode an interface value to Encoder buffer. // It will return none-nil error if x contains unsupported types // or buffer is not enough. -// It will check if x implements interface Packer and use x.Pack first. +// It will check if x implements interface BinaryEncoder and use x.Encode first. func (this *Encoder) Value(x interface{}) (err error) { defer func() { if e := recover(); e != nil { @@ -195,19 +195,19 @@ func (this *Encoder) Value(x interface{}) (err error) { v := reflect.ValueOf(x) - if p, ok := x.(Packer); ok { - if _, _ok := x.(Sizer); !_ok { //interface verification - panic(fmt.Errorf("expect but not Sizer: %s", v.Type().String())) + if p, ok := x.(BinaryEncoder); ok { + if _, _ok := x.(BinarySizer); !_ok { //interface verification + panic(fmt.Errorf("expect but not BinarySizer: %s", v.Type().String())) } - r, err := p.Pack(this.buff[this.pos:]) + r, err := p.Encode(this.buff[this.pos:]) if err == nil { this.reserve(len(r)) } return err } else { - if _, _ok := x.(Sizer); _ok { //interface verification - panic(fmt.Errorf("unexpected Sizer: %s", v.Type().String())) + if _, _ok := x.(BinarySizer); _ok { //interface verification + panic(fmt.Errorf("unexpected BinarySizer: %s", v.Type().String())) } } @@ -427,7 +427,7 @@ func (this *Encoder) value(v reflect.Value) error { this.String(v.String()) case reflect.Slice, reflect.Array: - if sizeofNilPointer(v.Type().Elem()) < 0 { //verify array element is valid + if !validUserType(v.Type().Elem()) { //verify array element is valid return fmt.Errorf("binary.Encoder.Value: unsupported type %s", v.Type().String()) } if this.boolArray(v) < 0 { //deal with bool array first @@ -441,8 +441,8 @@ func (this *Encoder) value(v reflect.Value) error { t := v.Type() kt := t.Key() vt := t.Elem() - if sizeofNilPointer(kt) < 0 || - sizeofNilPointer(vt) < 0 { //verify map key and value type are both valid + if !validUserType(kt) || + !validUserType(vt) { //verify map key and value type are both valid return fmt.Errorf("binary.Decoder.Value: unsupported type %s", v.Type().String()) } @@ -458,7 +458,7 @@ func (this *Encoder) value(v reflect.Value) error { return queryStruct(v.Type()).encode(this, v) case reflect.Ptr: - if sizeofNilPointer(v.Type()) < 0 { + if !validUserType(v.Type()) { return fmt.Errorf("binary.Encoder.Value: unsupported type %s", v.Type().String()) } if !v.IsNil() { diff --git a/example_test.go b/example_test.go index b2eade8..e7890a0 100644 --- a/example_test.go +++ b/example_test.go @@ -67,7 +67,7 @@ func ExamplePack() { s.A = 0x11223344 s.B = -5 s.C = "hello" - b, err := binary.Pack(s, nil) + b, err := binary.Encode(s, nil) if err != nil { fmt.Println("binary.Pack failed:", err) } @@ -86,7 +86,7 @@ func ExamplePack_withbuffer() { s.C = "hello" size := binary.Sizeof(s) buffer := make([]byte, size) - b, err := binary.Pack(s, buffer) + b, err := binary.Encode(s, buffer) if err != nil { fmt.Println("binary.Pack failed:", err) } @@ -101,7 +101,7 @@ func ExampleUnpack() { C string } buffer := []byte{0x44, 0x33, 0x22, 0x11, 0x9, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f} - err := binary.Unpack(buffer, &s) + err := binary.Decode(buffer, &s) if err != nil { fmt.Println("binary.Unpack failed:", err) } @@ -140,7 +140,7 @@ func (this *S) Size() int { size := binary.Sizeof(this.A) + binary.Sizeof(this.C) + binary.Sizeof(int16(this.B)) return size } -func (this *S) Pack(buffer []byte) ([]byte, error) { +func (this *S) Encode(buffer []byte) ([]byte, error) { buff, err := binary.MakeEncodeBuffer(this, buffer) if err != nil { return nil, err @@ -151,14 +151,14 @@ func (this *S) Pack(buffer []byte) ([]byte, error) { encoder.Value(this.C) return encoder.Buffer(), nil } -func (this *S) Unpack(buffer []byte) error { +func (this *S) Decode(buffer []byte) error { decoder := binary.NewDecoder(buffer) decoder.Value(&this.A) this.B = int(decoder.Int16()) decoder.Value(&this.C) return nil } -func ExamplePacker() { +func ExampleBinarySerializer() { /* type S struct { A uint32 @@ -169,14 +169,14 @@ func ExamplePacker() { size := binary.Sizeof(this.A) + binary.Sizeof(this.C) + binary.Sizeof(int16(this.B)) return size } - func (this *S) Pack() ([]byte, error) { + func (this *S) Encode() ([]byte, error) { encoder := binary.NewEncoder(this.Size()) encoder.Value(this.A) encoder.Int16(int16(this.B)) encoder.Value(this.C) return encoder.Buffer(), nil } - func (this *S) Unpack(buffer []byte) error { + func (this *S) Decode(buffer []byte) error { decoder := binary.NewDecoder(buffer) decoder.Value(&this.A) this.B = int(decoder.Int16()) @@ -188,12 +188,12 @@ func ExamplePacker() { s.A = 0x11223344 s.B = -5 s.C = "hello" - b, err := binary.Pack(&s, nil) + b, err := binary.Encode(&s, nil) if err != nil { fmt.Println("binary.Pack failed:", err) } - err = binary.Unpack(b, &ss) + err = binary.Decode(b, &ss) if err != nil { fmt.Println("binary.Unpack failed:", err) } diff --git a/export.go b/export.go index cacd692..cb64531 100644 --- a/export.go +++ b/export.go @@ -84,17 +84,17 @@ func Size(data interface{}) int { // Sizeof returns how many bytes Write would generate to encode the value v, which // must be a serialize-able value or a slice/map/struct of serialize-able values, or a pointer to such data. // If v is neither of these, Size returns -1. -// If data implements interface Sizer, it will use data.Size first. -// It will panic if data implements interface Sizer or Packer only. +// If data implements interface BinarySizer, it will use data.Size first. +// It will panic if data implements interface BinarySizer or BinaryEncoder only. func Sizeof(data interface{}) int { - if p, ok := data.(Sizer); ok { - if _, _ok := data.(Packer); !_ok { //interface verification - panic(errors.New("expect but not Packer:" + reflect.TypeOf(data).String())) + if p, ok := data.(BinarySizer); ok { + if _, _ok := data.(BinaryEncoder); !_ok { //interface verification + panic(errors.New("expect but not BinaryEncoder:" + reflect.TypeOf(data).String())) } return p.Size() } else { - if _, _ok := data.(Packer); _ok { //interface verification - panic(errors.New("unexpected Packer:" + reflect.TypeOf(data).String())) + if _, _ok := data.(BinaryEncoder); _ok { //interface verification + panic(errors.New("unexpected BinaryEncoder:" + reflect.TypeOf(data).String())) } } return sizeof(data) @@ -155,31 +155,32 @@ func Write(w io.Writer, endian Endian, data interface{}) error { return err } -// Sizer is an interface to define go data Size method. -type Sizer interface { +// BinarySizer is an interface to define go data Size method. +type BinarySizer interface { Size() int } -// Packer is an interface to define go data Pack method. +// BinaryEncoder is an interface to define go data Encode method. // buffer is nil-able -type Packer interface { - Pack(buffer []byte) ([]byte, error) +type BinaryEncoder interface { + Encode(buffer []byte) ([]byte, error) } -// Packer is an interface to define go data UnPack method. -type Unpacker interface { - Unpack(buffer []byte) error +// BinaryDecoder is an interface to define go data Decode method. +type BinaryDecoder interface { + Decode(buffer []byte) error } -type PackUnpacker interface { - Sizer - Packer - Unpacker +// interface BinarySerializer defines the go data Size/Encode/Decode method +type BinarySerializer interface { + BinarySizer + BinaryEncoder + BinaryDecoder } -// Pack encode go data to byte array. +// Encode marshal go data to byte array. // nil buffer is aviable, it will create new buffer if necessary. -func Pack(data interface{}, buffer []byte) ([]byte, error) { +func Encode(data interface{}, buffer []byte) ([]byte, error) { buff, err := MakeEncodeBuffer(data, buffer) if err != nil { return nil, err @@ -191,10 +192,10 @@ func Pack(data interface{}, buffer []byte) ([]byte, error) { return encoder.Buffer(), err } -// Unpack decode go data from byte array. +// Decode unmarshal go data from byte array. // data must be interface of pointer for modify. // It will make new pointer or slice/map for nil-field of data. -func Unpack(buffer []byte, data interface{}) error { +func Decode(buffer []byte, data interface{}) error { var decoder Decoder decoder.Init(buffer, DefaultEndian) return decoder.Value(data) diff --git a/func.go b/func.go index d0b7004..fa3af9a 100644 --- a/func.go +++ b/func.go @@ -194,7 +194,7 @@ func bitsOfValue(v reflect.Value, topLevel bool) int { bits = 1 } if v.IsNil() { - if topLevel || sizeofNilPointer(v.Type()) < 0 { + if topLevel || !validUserType(v.Type()) { return -1 } return 1 @@ -219,7 +219,7 @@ func bitsOfValue(v reflect.Value, topLevel bool) int { return sizeofFixArray(arrayLen, s)*8 + bits } else { sum := SizeofUvarint(uint64(arrayLen))*8 + bits //array size bytes num - if sizeofNilPointer(t.Elem()) < 0 { //check if array element type valid + if !validUserType(t.Elem()) { //check if array element type valid return -1 } for i, n := 0, arrayLen; i < n; i++ { @@ -234,8 +234,8 @@ func bitsOfValue(v reflect.Value, topLevel bool) int { sum := SizeofUvarint(uint64(mapLen))*8 + bits //array size keys := v.MapKeys() - if sizeofNilPointer(t.Key()) < 0 || - sizeofNilPointer(t.Elem()) < 0 { //check if map key and value type valid + if !validUserType(t.Key()) || + !validUserType(t.Elem()) { //check if map key and value type valid return -1 } @@ -276,12 +276,12 @@ func sizeofNilPointer(t reflect.Type) int { case reflect.String: return SizeofUvarint(0) case reflect.Slice: - if sizeofNilPointer(tt.Elem()) > 0 { //verify element type valid + if validUserType(tt.Elem()) { //verify element type valid return SizeofUvarint(0) } case reflect.Map: - if sizeofNilPointer(tt.Key()) > 0 && - sizeofNilPointer(tt.Elem()) > 0 { //verify key and value type valid + if validUserType(tt.Key()) && + validUserType(tt.Elem()) { //verify key and value type valid return SizeofUvarint(0) } case reflect.Array: @@ -326,7 +326,7 @@ func newPtr(v reflect.Value, decoder *Decoder, topLevel bool) bool { e := v.Type().Elem() switch e.Kind() { case reflect.Array, reflect.Struct, reflect.Slice, reflect.Map: - if sizeofNilPointer(e) < 0 { //check if valid pointer type + if !validUserType(e) { //check if valid pointer type return false } fallthrough @@ -379,3 +379,7 @@ func sizeofString(_len int) int { func sizeofFixArray(_len, elemLen int) int { return SizeofUvarint(uint64(_len)) + _len*elemLen } + +func validUserType(t reflect.Type) bool { + return sizeofNilPointer(t) >= 0 +}