diff options
Diffstat (limited to 'pkg/binary')
-rw-r--r-- | pkg/binary/BUILD | 16 | ||||
-rw-r--r-- | pkg/binary/binary.go | 266 | ||||
-rw-r--r-- | pkg/binary/binary_test.go | 266 |
3 files changed, 0 insertions, 548 deletions
diff --git a/pkg/binary/BUILD b/pkg/binary/BUILD deleted file mode 100644 index 7ca2fda90..000000000 --- a/pkg/binary/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -load("//tools:defs.bzl", "go_library", "go_test") - -package(licenses = ["notice"]) - -go_library( - name = "binary", - srcs = ["binary.go"], - visibility = ["//:sandbox"], -) - -go_test( - name = "binary_test", - size = "small", - srcs = ["binary_test.go"], - library = ":binary", -) diff --git a/pkg/binary/binary.go b/pkg/binary/binary.go deleted file mode 100644 index 25065aef9..000000000 --- a/pkg/binary/binary.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package binary translates between select fixed-sized types and a binary -// representation. -package binary - -import ( - "encoding/binary" - "fmt" - "io" - "reflect" -) - -// LittleEndian is the same as encoding/binary.LittleEndian. -// -// It is included here as a convenience. -var LittleEndian = binary.LittleEndian - -// BigEndian is the same as encoding/binary.BigEndian. -// -// It is included here as a convenience. -var BigEndian = binary.BigEndian - -// AppendUint16 appends the binary representation of a uint16 to buf. -func AppendUint16(buf []byte, order binary.ByteOrder, num uint16) []byte { - buf = append(buf, make([]byte, 2)...) - order.PutUint16(buf[len(buf)-2:], num) - return buf -} - -// AppendUint32 appends the binary representation of a uint32 to buf. -func AppendUint32(buf []byte, order binary.ByteOrder, num uint32) []byte { - buf = append(buf, make([]byte, 4)...) - order.PutUint32(buf[len(buf)-4:], num) - return buf -} - -// AppendUint64 appends the binary representation of a uint64 to buf. -func AppendUint64(buf []byte, order binary.ByteOrder, num uint64) []byte { - buf = append(buf, make([]byte, 8)...) - order.PutUint64(buf[len(buf)-8:], num) - return buf -} - -// Marshal appends a binary representation of data to buf. -// -// data must only contain fixed-length signed and unsigned ints, arrays, -// slices, structs and compositions of said types. data may be a pointer, -// but cannot contain pointers. -func Marshal(buf []byte, order binary.ByteOrder, data interface{}) []byte { - return marshal(buf, order, reflect.Indirect(reflect.ValueOf(data))) -} - -func marshal(buf []byte, order binary.ByteOrder, data reflect.Value) []byte { - switch data.Kind() { - case reflect.Int8: - buf = append(buf, byte(int8(data.Int()))) - case reflect.Int16: - buf = AppendUint16(buf, order, uint16(int16(data.Int()))) - case reflect.Int32: - buf = AppendUint32(buf, order, uint32(int32(data.Int()))) - case reflect.Int64: - buf = AppendUint64(buf, order, uint64(data.Int())) - - case reflect.Uint8: - buf = append(buf, byte(data.Uint())) - case reflect.Uint16: - buf = AppendUint16(buf, order, uint16(data.Uint())) - case reflect.Uint32: - buf = AppendUint32(buf, order, uint32(data.Uint())) - case reflect.Uint64: - buf = AppendUint64(buf, order, data.Uint()) - - case reflect.Array, reflect.Slice: - for i, l := 0, data.Len(); i < l; i++ { - buf = marshal(buf, order, data.Index(i)) - } - - case reflect.Struct: - for i, l := 0, data.NumField(); i < l; i++ { - buf = marshal(buf, order, data.Field(i)) - } - - default: - panic("invalid type: " + data.Type().String()) - } - return buf -} - -// Unmarshal unpacks buf into data. -// -// data must be a slice or a pointer and buf must have a length of exactly -// Size(data). data must only contain fixed-length signed and unsigned ints, -// arrays, slices, structs and compositions of said types. -func Unmarshal(buf []byte, order binary.ByteOrder, data interface{}) { - value := reflect.ValueOf(data) - switch value.Kind() { - case reflect.Ptr: - value = value.Elem() - case reflect.Slice: - default: - panic("invalid type: " + value.Type().String()) - } - buf = unmarshal(buf, order, value) - if len(buf) != 0 { - panic(fmt.Sprintf("buffer too long by %d bytes", len(buf))) - } -} - -func unmarshal(buf []byte, order binary.ByteOrder, data reflect.Value) []byte { - switch data.Kind() { - case reflect.Int8: - data.SetInt(int64(int8(buf[0]))) - buf = buf[1:] - case reflect.Int16: - data.SetInt(int64(int16(order.Uint16(buf)))) - buf = buf[2:] - case reflect.Int32: - data.SetInt(int64(int32(order.Uint32(buf)))) - buf = buf[4:] - case reflect.Int64: - data.SetInt(int64(order.Uint64(buf))) - buf = buf[8:] - - case reflect.Uint8: - data.SetUint(uint64(buf[0])) - buf = buf[1:] - case reflect.Uint16: - data.SetUint(uint64(order.Uint16(buf))) - buf = buf[2:] - case reflect.Uint32: - data.SetUint(uint64(order.Uint32(buf))) - buf = buf[4:] - case reflect.Uint64: - data.SetUint(order.Uint64(buf)) - buf = buf[8:] - - case reflect.Array, reflect.Slice: - for i, l := 0, data.Len(); i < l; i++ { - buf = unmarshal(buf, order, data.Index(i)) - } - - case reflect.Struct: - for i, l := 0, data.NumField(); i < l; i++ { - if field := data.Field(i); field.CanSet() { - buf = unmarshal(buf, order, field) - } else { - buf = buf[sizeof(field):] - } - } - - default: - panic("invalid type: " + data.Type().String()) - } - return buf -} - -// Size calculates the buffer sized needed by Marshal or Unmarshal. -// -// Size only support the types supported by Marshal. -func Size(v interface{}) uintptr { - return sizeof(reflect.Indirect(reflect.ValueOf(v))) -} - -func sizeof(data reflect.Value) uintptr { - switch data.Kind() { - case reflect.Int8, reflect.Uint8: - return 1 - case reflect.Int16, reflect.Uint16: - return 2 - case reflect.Int32, reflect.Uint32: - return 4 - case reflect.Int64, reflect.Uint64: - return 8 - - case reflect.Array, reflect.Slice: - var size uintptr - for i, l := 0, data.Len(); i < l; i++ { - size += sizeof(data.Index(i)) - } - return size - - case reflect.Struct: - var size uintptr - for i, l := 0, data.NumField(); i < l; i++ { - size += sizeof(data.Field(i)) - } - return size - - default: - panic("invalid type: " + data.Type().String()) - } -} - -// ReadUint16 reads a uint16 from r. -func ReadUint16(r io.Reader, order binary.ByteOrder) (uint16, error) { - buf := make([]byte, 2) - if _, err := io.ReadFull(r, buf); err != nil { - return 0, err - } - return order.Uint16(buf), nil -} - -// ReadUint32 reads a uint32 from r. -func ReadUint32(r io.Reader, order binary.ByteOrder) (uint32, error) { - buf := make([]byte, 4) - if _, err := io.ReadFull(r, buf); err != nil { - return 0, err - } - return order.Uint32(buf), nil -} - -// ReadUint64 reads a uint64 from r. -func ReadUint64(r io.Reader, order binary.ByteOrder) (uint64, error) { - buf := make([]byte, 8) - if _, err := io.ReadFull(r, buf); err != nil { - return 0, err - } - return order.Uint64(buf), nil -} - -// WriteUint16 writes a uint16 to w. -func WriteUint16(w io.Writer, order binary.ByteOrder, num uint16) error { - buf := make([]byte, 2) - order.PutUint16(buf, num) - _, err := w.Write(buf) - return err -} - -// WriteUint32 writes a uint32 to w. -func WriteUint32(w io.Writer, order binary.ByteOrder, num uint32) error { - buf := make([]byte, 4) - order.PutUint32(buf, num) - _, err := w.Write(buf) - return err -} - -// WriteUint64 writes a uint64 to w. -func WriteUint64(w io.Writer, order binary.ByteOrder, num uint64) error { - buf := make([]byte, 8) - order.PutUint64(buf, num) - _, err := w.Write(buf) - return err -} - -// AlignUp rounds a length up to an alignment. align must be a power of 2. -func AlignUp(length int, align uint) int { - return (length + int(align) - 1) & ^(int(align) - 1) -} - -// AlignDown rounds a length down to an alignment. align must be a power of 2. -func AlignDown(length int, align uint) int { - return length & ^(int(align) - 1) -} diff --git a/pkg/binary/binary_test.go b/pkg/binary/binary_test.go deleted file mode 100644 index 4d609a438..000000000 --- a/pkg/binary/binary_test.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2018 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package binary - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "reflect" - "strings" - "testing" -) - -func newInt32(i int32) *int32 { - return &i -} - -func TestSize(t *testing.T) { - if got, want := Size(uint32(10)), uintptr(4); got != want { - t.Errorf("Got = %d, want = %d", got, want) - } -} - -func TestPanic(t *testing.T) { - tests := []struct { - name string - f func([]byte, binary.ByteOrder, interface{}) - data interface{} - want string - }{ - {"Unmarshal int", Unmarshal, 5, "invalid type: int"}, - {"Unmarshal []int", Unmarshal, []int{5}, "invalid type: int"}, - {"Marshal int", func(_ []byte, bo binary.ByteOrder, d interface{}) { Marshal(nil, bo, d) }, 5, "invalid type: int"}, - {"Marshal int[]", func(_ []byte, bo binary.ByteOrder, d interface{}) { Marshal(nil, bo, d) }, []int{5}, "invalid type: int"}, - {"Unmarshal short buffer", Unmarshal, newInt32(5), "runtime error: index out of range"}, - {"Unmarshal long buffer", func(_ []byte, bo binary.ByteOrder, d interface{}) { Unmarshal(make([]byte, 50), bo, d) }, newInt32(5), "buffer too long by 46 bytes"}, - {"marshal int", func(_ []byte, bo binary.ByteOrder, d interface{}) { marshal(nil, bo, reflect.ValueOf(d)) }, 5, "invalid type: int"}, - {"Size int", func(_ []byte, _ binary.ByteOrder, d interface{}) { Size(d) }, 5, "invalid type: int"}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - defer func() { - r := recover() - if got := fmt.Sprint(r); !strings.HasPrefix(got, test.want) { - t.Errorf("Got recover() = %q, want prefix = %q", got, test.want) - } - }() - - test.f(nil, LittleEndian, test.data) - }) - } -} - -type inner struct { - Field int32 -} - -type outer struct { - Int8 int8 - Int16 int16 - Int32 int32 - Int64 int64 - Uint8 uint8 - Uint16 uint16 - Uint32 uint32 - Uint64 uint64 - - Slice []int32 - Array [5]int32 - Struct inner -} - -func TestMarshalUnmarshal(t *testing.T) { - want := outer{ - 1, 2, 3, 4, 5, 6, 7, 8, - []int32{9, 10, 11}, - [5]int32{12, 13, 14, 15, 16}, - inner{17}, - } - buf := Marshal(nil, LittleEndian, want) - got := outer{Slice: []int32{0, 0, 0}} - Unmarshal(buf, LittleEndian, &got) - if !reflect.DeepEqual(&got, &want) { - t.Errorf("Got = %#v, want = %#v", got, want) - } -} - -type outerBenchmark struct { - Int8 int8 - Int16 int16 - Int32 int32 - Int64 int64 - Uint8 uint8 - Uint16 uint16 - Uint32 uint32 - Uint64 uint64 - - Array [5]int32 - Struct inner -} - -func BenchmarkMarshalUnmarshal(b *testing.B) { - b.ReportAllocs() - - in := outerBenchmark{ - 1, 2, 3, 4, 5, 6, 7, 8, - [5]int32{9, 10, 11, 12, 13}, - inner{14}, - } - buf := make([]byte, Size(&in)) - out := outerBenchmark{} - - for i := 0; i < b.N; i++ { - buf := Marshal(buf[:0], LittleEndian, &in) - Unmarshal(buf, LittleEndian, &out) - } -} - -func BenchmarkReadWrite(b *testing.B) { - b.ReportAllocs() - - in := outerBenchmark{ - 1, 2, 3, 4, 5, 6, 7, 8, - [5]int32{9, 10, 11, 12, 13}, - inner{14}, - } - buf := bytes.NewBuffer(make([]byte, binary.Size(&in))) - out := outerBenchmark{} - - for i := 0; i < b.N; i++ { - buf.Reset() - if err := binary.Write(buf, LittleEndian, &in); err != nil { - b.Error("Write:", err) - } - if err := binary.Read(buf, LittleEndian, &out); err != nil { - b.Error("Read:", err) - } - } -} - -type outerPadding struct { - _ int8 - _ int16 - _ int32 - _ int64 - _ uint8 - _ uint16 - _ uint32 - _ uint64 - - _ []int32 - _ [5]int32 - _ inner -} - -func TestMarshalUnmarshalPadding(t *testing.T) { - var want outerPadding - buf := Marshal(nil, LittleEndian, want) - var got outerPadding - Unmarshal(buf, LittleEndian, &got) - if !reflect.DeepEqual(&got, &want) { - t.Errorf("Got = %#v, want = %#v", got, want) - } -} - -// Numbers with bits in every byte that distinguishable in big and little endian. -const ( - want16 = 64<<8 | 128 - want32 = 16<<24 | 32<<16 | want16 - want64 = 1<<56 | 2<<48 | 4<<40 | 8<<32 | want32 -) - -func TestReadWriteUint16(t *testing.T) { - const want = uint16(want16) - var buf bytes.Buffer - if err := WriteUint16(&buf, LittleEndian, want); err != nil { - t.Error("WriteUint16:", err) - } - got, err := ReadUint16(&buf, LittleEndian) - if err != nil { - t.Error("ReadUint16:", err) - } - if got != want { - t.Errorf("got = %d, want = %d", got, want) - } -} - -func TestReadWriteUint32(t *testing.T) { - const want = uint32(want32) - var buf bytes.Buffer - if err := WriteUint32(&buf, LittleEndian, want); err != nil { - t.Error("WriteUint32:", err) - } - got, err := ReadUint32(&buf, LittleEndian) - if err != nil { - t.Error("ReadUint32:", err) - } - if got != want { - t.Errorf("got = %d, want = %d", got, want) - } -} - -func TestReadWriteUint64(t *testing.T) { - const want = uint64(want64) - var buf bytes.Buffer - if err := WriteUint64(&buf, LittleEndian, want); err != nil { - t.Error("WriteUint64:", err) - } - got, err := ReadUint64(&buf, LittleEndian) - if err != nil { - t.Error("ReadUint64:", err) - } - if got != want { - t.Errorf("got = %d, want = %d", got, want) - } -} - -type readWriter struct { - err error -} - -func (rw *readWriter) Write([]byte) (int, error) { - return 0, rw.err -} - -func (rw *readWriter) Read([]byte) (int, error) { - return 0, rw.err -} - -func TestReadWriteError(t *testing.T) { - tests := []struct { - name string - f func(rw io.ReadWriter) error - }{ - {"WriteUint16", func(rw io.ReadWriter) error { return WriteUint16(rw, LittleEndian, 0) }}, - {"ReadUint16", func(rw io.ReadWriter) error { _, err := ReadUint16(rw, LittleEndian); return err }}, - {"WriteUint32", func(rw io.ReadWriter) error { return WriteUint32(rw, LittleEndian, 0) }}, - {"ReadUint32", func(rw io.ReadWriter) error { _, err := ReadUint32(rw, LittleEndian); return err }}, - {"WriteUint64", func(rw io.ReadWriter) error { return WriteUint64(rw, LittleEndian, 0) }}, - {"ReadUint64", func(rw io.ReadWriter) error { _, err := ReadUint64(rw, LittleEndian); return err }}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - want := errors.New("want") - if got := test.f(&readWriter{want}); got != want { - t.Errorf("got = %v, want = %v", got, want) - } - }) - } -} |