diff options
Diffstat (limited to 'libgo/go/encoding/binary')
-rw-r--r-- | libgo/go/encoding/binary/binary.go | 57 | ||||
-rw-r--r-- | libgo/go/encoding/binary/binary_test.go | 9 | ||||
-rw-r--r-- | libgo/go/encoding/binary/varint.go | 1 |
3 files changed, 39 insertions, 28 deletions
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go index 04d5723..edbac19 100644 --- a/libgo/go/encoding/binary/binary.go +++ b/libgo/go/encoding/binary/binary.go @@ -167,9 +167,9 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { default: return errors.New("binary.Read: invalid type " + d.Type().String()) } - size := dataSize(v) - if size < 0 { - return errors.New("binary.Read: invalid type " + v.Type().String()) + size, err := dataSize(v) + if err != nil { + return errors.New("binary.Read: " + err.Error()) } d := &decoder{order: order, buf: make([]byte, size)} if _, err := io.ReadFull(r, d.buf); err != nil { @@ -247,64 +247,68 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error { // Fallback to reflect-based encoding. v := reflect.Indirect(reflect.ValueOf(data)) - size := dataSize(v) - if size < 0 { - return errors.New("binary.Write: invalid type " + v.Type().String()) + size, err := dataSize(v) + if err != nil { + return errors.New("binary.Write: " + err.Error()) } buf := make([]byte, size) e := &encoder{order: order, buf: buf} e.value(v) - _, err := w.Write(buf) + _, err = w.Write(buf) return err } // Size returns how many bytes Write would generate to encode the value v, which // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. func Size(v interface{}) int { - return dataSize(reflect.Indirect(reflect.ValueOf(v))) + n, err := dataSize(reflect.Indirect(reflect.ValueOf(v))) + if err != nil { + return -1 + } + return n } // dataSize returns the number of bytes the actual data represented by v occupies in memory. // For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice // it returns the length of the slice times the element size and does not count the memory // occupied by the header. -func dataSize(v reflect.Value) int { +func dataSize(v reflect.Value) (int, error) { if v.Kind() == reflect.Slice { - elem := sizeof(v.Type().Elem()) - if elem < 0 { - return -1 + elem, err := sizeof(v.Type().Elem()) + if err != nil { + return 0, err } - return v.Len() * elem + return v.Len() * elem, nil } return sizeof(v.Type()) } -func sizeof(t reflect.Type) int { +func sizeof(t reflect.Type) (int, error) { switch t.Kind() { case reflect.Array: - n := sizeof(t.Elem()) - if n < 0 { - return -1 + n, err := sizeof(t.Elem()) + if err != nil { + return 0, err } - return t.Len() * n + return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { - s := sizeof(t.Field(i).Type) - if s < 0 { - return -1 + s, err := sizeof(t.Field(i).Type) + if err != nil { + return 0, err } sum += s } - return sum + return sum, nil case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: - return int(t.Size()) + return int(t.Size()), nil } - return -1 + return 0, errors.New("invalid type " + t.String()) } type coder struct { @@ -514,11 +518,12 @@ func (e *encoder) value(v reflect.Value) { } func (d *decoder) skip(v reflect.Value) { - d.buf = d.buf[dataSize(v):] + n, _ := dataSize(v) + d.buf = d.buf[n:] } func (e *encoder) skip(v reflect.Value) { - n := dataSize(v) + n, _ := dataSize(v) for i := range e.buf[0:n] { e.buf[i] = 0 } diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go index cfad8d3..056f099 100644 --- a/libgo/go/encoding/binary/binary_test.go +++ b/libgo/go/encoding/binary/binary_test.go @@ -9,6 +9,7 @@ import ( "io" "math" "reflect" + "strings" "testing" ) @@ -149,8 +150,14 @@ func TestWriteT(t *testing.T) { tv := reflect.Indirect(reflect.ValueOf(ts)) for i, n := 0, tv.NumField(); i < n; i++ { + typ := tv.Field(i).Type().String() + if typ == "[4]int" { + typ = "int" // the problem is int, not the [4] + } if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil { t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type()) + } else if !strings.Contains(err.Error(), typ) { + t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ) } } } @@ -238,7 +245,7 @@ func BenchmarkReadStruct(b *testing.B) { bsr := &byteSliceReader{} var buf bytes.Buffer Write(&buf, BigEndian, &s) - n := dataSize(reflect.ValueOf(s)) + n, _ := dataSize(reflect.ValueOf(s)) b.SetBytes(int64(n)) t := s b.ResetTimer() diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go index 7035529..3a2dfa3c 100644 --- a/libgo/go/encoding/binary/varint.go +++ b/libgo/go/encoding/binary/varint.go @@ -120,7 +120,6 @@ func ReadUvarint(r io.ByteReader) (uint64, error) { x |= uint64(b&0x7f) << s s += 7 } - panic("unreachable") } // ReadVarint reads an encoded signed integer from r and returns it as an int64. |