1
0
mirror of https://github.com/taigrr/arc synced 2025-01-18 04:33:13 -08:00

initial import

This commit is contained in:
Will
2016-05-22 22:16:37 +09:00
commit 0075ef607f
256 changed files with 58234 additions and 0 deletions

140
binary/binary.go Normal file
View File

@@ -0,0 +1,140 @@
// Copyright (C) 2016 - Will Glozer. All rights reserved.
package binary
import (
"encoding/binary"
"io"
"reflect"
)
type ByteOrder binary.ByteOrder
var (
BE ByteOrder = binary.BigEndian
LE ByteOrder = binary.LittleEndian
)
func Write(w io.Writer, order ByteOrder, data interface{}) error {
v := reflect.Indirect(reflect.ValueOf(data))
t := v.Type()
out := make([]byte, size(v, t))
buf := out
for i := 0; i < t.NumField(); i++ {
v := v.Field(i)
t := v.Type()
if skip(v, t) {
continue
}
switch t.Kind() {
case reflect.Int8:
buf[0] = byte(v.Int())
case reflect.Uint8:
buf[0] = byte(v.Uint())
case reflect.Int16:
order.PutUint16(buf, uint16(v.Int()))
case reflect.Uint16:
order.PutUint16(buf, uint16(v.Uint()))
case reflect.Int32:
order.PutUint32(buf, uint32(v.Int()))
case reflect.Uint32:
order.PutUint32(buf, uint32(v.Uint()))
case reflect.Int64:
order.PutUint64(buf, uint64(v.Int()))
case reflect.Uint64:
order.PutUint64(buf, uint64(v.Uint()))
case reflect.Array:
copy(buf, v.Slice(0, v.Len()).Bytes())
}
buf = buf[t.Size():]
}
_, err := w.Write(out)
return err
}
func Read(r io.Reader, order ByteOrder, data interface{}) error {
v := reflect.Indirect(reflect.ValueOf(data))
t := v.Type()
buf := make([]byte, size(v, t))
_, err := io.ReadFull(r, buf)
if err != nil {
return err
}
for i := 0; i < t.NumField(); i++ {
v := v.Field(i)
t := v.Type()
if skip(v, t) {
continue
}
switch t.Kind() {
case reflect.Int8:
v.SetInt(int64(buf[0]))
case reflect.Uint8:
v.SetUint(uint64(buf[0]))
case reflect.Int16:
v.SetInt(int64(order.Uint16(buf)))
case reflect.Uint16:
v.SetUint(uint64(order.Uint16(buf)))
case reflect.Int32:
v.SetInt(int64(order.Uint32(buf)))
case reflect.Uint32:
v.SetUint(uint64(order.Uint32(buf)))
case reflect.Int64:
v.SetInt(int64(order.Uint64(buf)))
case reflect.Uint64:
v.SetUint(uint64(order.Uint64(buf)))
case reflect.Array:
reflect.Copy(v, reflect.ValueOf(buf))
}
buf = buf[t.Size():]
}
return nil
}
func size(v reflect.Value, t reflect.Type) uintptr {
size := uintptr(0)
for i := 0; i < t.NumField(); i++ {
v := v.Field(i)
t := v.Type()
if !skip(v, t) {
size += t.Size()
}
}
return size
}
func skip(v reflect.Value, t reflect.Type) bool {
if !v.CanSet() {
return true
}
switch t.Kind() {
case reflect.Int8, reflect.Uint8:
return false
case reflect.Int16, reflect.Uint16:
return false
case reflect.Int32, reflect.Uint32:
return false
case reflect.Int64, reflect.Uint64:
return false
case reflect.Array:
return t.Elem().Size() != 1
}
return true
}

168
binary/binary_test.go Normal file
View File

@@ -0,0 +1,168 @@
// Copyright (C) 2016 - Will Glozer. All rights reserved.
package binary
import (
"bytes"
"encoding/binary"
"math"
"reflect"
"testing"
)
func TestBinaryArray(t *testing.T) {
type Values struct {
Byte byte
Array [3]byte
Int64 int64
}
in := &Values{1, [3]byte{2, 3, 4}, 0xAC00BD00}
buf := &bytes.Buffer{}
out := &Values{}
if err := Write(buf, binary.LittleEndian, in); err != nil {
t.Fatal(err)
}
if err := Read(buf, binary.LittleEndian, out); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(in, out) {
t.Fatalf("round trip serialization failed")
}
}
func TestBinaryMinMax(t *testing.T) {
type Values struct {
MinInt8 int8
MaxInt8 int8
MaxUint8 uint8
MinInt16 int16
MaxInt16 int16
MaxUint16 uint16
MinInt32 int32
MaxInt32 int32
MaxUint32 uint32
MinInt64 int64
MaxInt64 int64
MaxUint64 uint64
}
in := &Values{
MinInt8: math.MinInt8,
MaxInt8: math.MaxInt8,
MaxUint8: 1<<8 - 1,
MinInt16: math.MinInt16,
MaxInt16: math.MaxInt16,
MaxUint16: 1<<16 - 1,
MinInt32: math.MinInt32,
MaxInt32: math.MaxInt32,
MaxUint32: 1<<32 - 1,
MinInt64: math.MinInt64,
MaxInt64: math.MaxInt64,
MaxUint64: 1<<64 - 1,
}
out := &Values{}
buf := &bytes.Buffer{}
if err := Write(buf, binary.LittleEndian, in); err != nil {
t.Fatal(err)
}
if err := Read(buf, binary.LittleEndian, out); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(in, out) {
t.Fatalf("round trip serialization failed")
}
}
func TestBinaryByteOrder(t *testing.T) {
type Values struct {
Uint16 uint16
Uint32 uint32
Uint64 uint64
}
in := &Values{
Uint16: 0x1234,
Uint32: 0x12345678,
Uint64: 0x1234567890ABCDEF,
}
little := []byte{0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12}
buf := &bytes.Buffer{}
if err := Write(buf, binary.LittleEndian, in); err != nil {
t.Fatal(err)
}
if !bytes.Equal(buf.Bytes()[0:2], little[6:8]) {
t.Fatalf("uint16 little endian incorrect")
}
if !bytes.Equal(buf.Bytes()[2:6], little[4:8]) {
t.Fatalf("uint32 little endian incorrect")
}
if !bytes.Equal(buf.Bytes()[6:14], little[0:8]) {
t.Fatalf("uint64 little endian incorrect")
}
buf.Reset()
big := []byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}
if err := Write(buf, binary.BigEndian, in); err != nil {
t.Fatal(err)
}
if !bytes.Equal(buf.Bytes()[0:2], big[0:2]) {
t.Fatalf("uint16 big endian incorrect")
}
if !bytes.Equal(buf.Bytes()[2:6], big[0:4]) {
t.Fatalf("uint32 big endian incorrect")
}
if !bytes.Equal(buf.Bytes()[6:14], big[0:8]) {
t.Fatalf("uint64 big endian incorrect")
}
}
func TestBinarySkip(t *testing.T) {
type Values struct {
A byte
B string
C int32
D []byte
e byte
}
in := &Values{1, "foo", 0xABCDEF, []byte("bar"), 2}
out := &Values{}
buf := &bytes.Buffer{}
if err := Write(buf, binary.LittleEndian, in); err != nil {
t.Fatal(err)
}
if err := Read(buf, binary.LittleEndian, out); err != nil {
t.Fatal(err)
}
in.B = ""
in.D = nil
in.e = 0
if !reflect.DeepEqual(in, out) {
t.Fatal("round trip serialization failed")
}
}