diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-05-11 11:56:15 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-05-11 11:56:15 -0600 |
commit | 7e9213c75b9361c174f4662ff3feb4104d2c8f07 (patch) | |
tree | 46e37147b439add714cb6b49032ca38612596616 /pkg/binstruct | |
parent | 2744e0700ca6fe956f569d47010fd4e693fedcfa (diff) |
wip
Diffstat (limited to 'pkg/binstruct')
-rw-r--r-- | pkg/binstruct/binstruct_test.go | 15 | ||||
-rw-r--r-- | pkg/binstruct/l1.go | 49 |
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, |