summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-05-11 11:56:15 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-05-11 11:56:15 -0600
commit7e9213c75b9361c174f4662ff3feb4104d2c8f07 (patch)
tree46e37147b439add714cb6b49032ca38612596616 /pkg
parent2744e0700ca6fe956f569d47010fd4e693fedcfa (diff)
wip
Diffstat (limited to 'pkg')
-rw-r--r--pkg/binstruct/binstruct_test.go15
-rw-r--r--pkg/binstruct/l1.go49
2 files changed, 52 insertions, 12 deletions
diff --git a/pkg/binstruct/binstruct_test.go b/pkg/binstruct/binstruct_test.go
index 33a2f0a..fc7eab4 100644
--- a/pkg/binstruct/binstruct_test.go
+++ b/pkg/binstruct/binstruct_test.go
@@ -10,6 +10,7 @@ import (
func TestSmoke(t *testing.T) {
type UUID [16]byte
+ type PhysicalAddr int64
type DevItem struct {
DeviceID uint64 `bin:"off=0, siz=8, desc=device id"`
@@ -33,17 +34,23 @@ func TestSmoke(t *testing.T) {
binstruct.End `bin:"off=62"`
}
type TestType struct {
- Magic [5]byte `bin:"off=0,siz=5"`
- Dev DevItem `bin:"off=5,siz=62"`
+ Magic [5]byte `bin:"off=0,siz=5"`
+ Dev DevItem `bin:"off=5,siz=62"`
+ Addr PhysicalAddr `bin:"off=67, siz=8"`
- binstruct.End `bin:"off=67"`
+ binstruct.End `bin:"off=6F"`
}
input := TestType{}
copy(input.Magic[:], "mAgIc")
input.Dev.DeviceID = 12
+ input.Addr = 0xBEEF
bs, err := binstruct.Marshal(input)
assert.NoError(t, err)
- assert.True(t, len(bs) == 0x67, "len(bs)=0x%x", len(bs))
+ assert.True(t, len(bs) == 0x6F, "len(bs)=0x%x", len(bs))
+
+ var output TestType
+ assert.NoError(t, binstruct.Unmarshal(bs, &output))
+ assert.Equal(t, input, output)
}
diff --git a/pkg/binstruct/l1.go b/pkg/binstruct/l1.go
index e76e7d0..d90ecba 100644
--- a/pkg/binstruct/l1.go
+++ b/pkg/binstruct/l1.go
@@ -6,12 +6,35 @@ import (
"reflect"
)
+type Marshaler interface {
+ MarshalBinary() []byte
+ UnmarshalBinary([]byte)
+ BinarySize() int64
+}
+
type handler interface {
Unmarshal(dat []byte) interface{}
Marshal(val interface{}) []byte
Size() int64
}
+type extHandler struct {
+ typ reflect.Type
+}
+
+func (_ extHandler) Marshal(val interface{}) []byte {
+ return val.(Marshaler).MarshalBinary()
+}
+func (e extHandler) Unmarshal(dat []byte) interface{} {
+ val := reflect.New(e.typ).Elem().Interface().(Marshaler)
+ val.UnmarshalBinary(dat)
+ return val
+}
+func (e extHandler) Size() int64 {
+ val := reflect.New(e.typ).Elem().Interface().(Marshaler)
+ return val.BinarySize()
+}
+
type primitive struct {
unmarshal func(dat []byte) interface{}
marshal func(val interface{}) []byte
@@ -24,7 +47,17 @@ func (p primitive) Size() int64 { return p.size }
var _ handler = primitive{}
+func convert[T any](in interface{}) T {
+ var dstTyp T
+ return reflect.ValueOf(in).Convert(reflect.TypeOf(dstTyp)).Interface().(T)
+}
+
func genHandler(typ reflect.Type) (handler, error) {
+ if _, ok := reflect.New(typ).Elem().Interface().(Marshaler); ok {
+ return extHandler{
+ typ: typ,
+ }, nil
+ }
switch typ.Kind() {
case reflect.Invalid: // invalid
return nil, fmt.Errorf("unsupported kind: %s: %v", typ.Kind(), typ)
@@ -41,7 +74,7 @@ func genHandler(typ reflect.Type) (handler, error) {
case reflect.Uint8:
return primitive{
unmarshal: func(dat []byte) interface{} { return dat[0] },
- marshal: func(val interface{}) []byte { return []byte{val.(uint8)} },
+ marshal: func(val interface{}) []byte { return []byte{convert[uint8](val)} },
size: 1,
}, nil
case reflect.Uint16:
@@ -49,7 +82,7 @@ func genHandler(typ reflect.Type) (handler, error) {
unmarshal: func(dat []byte) interface{} { return binary.LittleEndian.Uint16(dat) },
marshal: func(val interface{}) []byte {
var buf [2]byte
- binary.LittleEndian.PutUint16(buf[:], val.(uint16))
+ binary.LittleEndian.PutUint16(buf[:], convert[uint16](val))
return buf[:]
},
size: 2,
@@ -59,7 +92,7 @@ func genHandler(typ reflect.Type) (handler, error) {
unmarshal: func(dat []byte) interface{} { return binary.LittleEndian.Uint32(dat) },
marshal: func(val interface{}) []byte {
var buf [4]byte
- binary.LittleEndian.PutUint32(buf[:], val.(uint32))
+ binary.LittleEndian.PutUint32(buf[:], convert[uint32](val))
return buf[:]
},
size: 4,
@@ -69,7 +102,7 @@ func genHandler(typ reflect.Type) (handler, error) {
unmarshal: func(dat []byte) interface{} { return binary.LittleEndian.Uint64(dat) },
marshal: func(val interface{}) []byte {
var buf [8]byte
- binary.LittleEndian.PutUint64(buf[:], val.(uint64))
+ binary.LittleEndian.PutUint64(buf[:], convert[uint64](val))
return buf[:]
},
size: 8,
@@ -79,7 +112,7 @@ func genHandler(typ reflect.Type) (handler, error) {
case reflect.Int8:
return primitive{
unmarshal: func(dat []byte) interface{} { return int8(dat[0]) },
- marshal: func(val interface{}) []byte { return []byte{uint8(val.(int8))} },
+ marshal: func(val interface{}) []byte { return []byte{uint8(convert[int8](val))}},
size: 1,
}, nil
case reflect.Int16:
@@ -87,7 +120,7 @@ func genHandler(typ reflect.Type) (handler, error) {
unmarshal: func(dat []byte) interface{} { return int16(binary.LittleEndian.Uint16(dat)) },
marshal: func(val interface{}) []byte {
var buf [2]byte
- binary.LittleEndian.PutUint16(buf[:], uint16(val.(int16)))
+ binary.LittleEndian.PutUint16(buf[:], uint16(convert[int16](val)))
return buf[:]
},
size: 2,
@@ -97,7 +130,7 @@ func genHandler(typ reflect.Type) (handler, error) {
unmarshal: func(dat []byte) interface{} { return int32(binary.LittleEndian.Uint32(dat)) },
marshal: func(val interface{}) []byte {
var buf [4]byte
- binary.LittleEndian.PutUint32(buf[:], uint32(val.(int32)))
+ binary.LittleEndian.PutUint32(buf[:], uint32(convert[int32](val)))
return buf[:]
},
size: 4,
@@ -107,7 +140,7 @@ func genHandler(typ reflect.Type) (handler, error) {
unmarshal: func(dat []byte) interface{} { return int64(binary.LittleEndian.Uint64(dat)) },
marshal: func(val interface{}) []byte {
var buf [8]byte
- binary.LittleEndian.PutUint64(buf[:], uint64(val.(int64)))
+ binary.LittleEndian.PutUint64(buf[:], uint64(convert[int64](val)))
return buf[:]
},
size: 8,