From 27401b6ea459921a6152ab1744da1618358465f4 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 10 Jul 2022 13:18:30 -0600 Subject: Rename the module, mv pkg lib --- lib/binstruct/unmarshal.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/binstruct/unmarshal.go (limited to 'lib/binstruct/unmarshal.go') diff --git a/lib/binstruct/unmarshal.go b/lib/binstruct/unmarshal.go new file mode 100644 index 0000000..1959d45 --- /dev/null +++ b/lib/binstruct/unmarshal.go @@ -0,0 +1,54 @@ +package binstruct + +import ( + "fmt" + "reflect" +) + +type Unmarshaler interface { + UnmarshalBinary([]byte) (int, error) +} + +func Unmarshal(dat []byte, dstPtr any) (int, error) { + if unmar, ok := dstPtr.(Unmarshaler); ok { + return unmar.UnmarshalBinary(dat) + } + return UnmarshalWithoutInterface(dat, dstPtr) +} + +func UnmarshalWithoutInterface(dat []byte, dstPtr any) (int, error) { + _dstPtr := reflect.ValueOf(dstPtr) + if _dstPtr.Kind() != reflect.Ptr { + return 0, fmt.Errorf("not a pointer: %v", _dstPtr.Type()) + } + dst := _dstPtr.Elem() + + switch dst.Kind() { + case reflect.Uint8, reflect.Int8, reflect.Uint16, reflect.Int16, reflect.Uint32, reflect.Int32, reflect.Uint64, reflect.Int64: + typ := intKind2Type[dst.Kind()] + newDstPtr := reflect.New(typ) + n, err := Unmarshal(dat, newDstPtr.Interface()) + dst.Set(newDstPtr.Elem().Convert(dst.Type())) + return n, err + case reflect.Ptr: + elemPtr := reflect.New(dst.Type().Elem()) + n, err := Unmarshal(dat, elemPtr.Interface()) + dst.Set(elemPtr.Convert(dst.Type())) + return n, err + case reflect.Array: + var n int + for i := 0; i < dst.Len(); i++ { + _n, err := Unmarshal(dat[n:], dst.Index(i).Addr().Interface()) + n += _n + if err != nil { + return n, err + } + } + return n, nil + case reflect.Struct: + return getStructHandler(dst.Type()).Unmarshal(dat, dst) + default: + panic(fmt.Errorf("type=%v does not implement binfmt.Unmarshaler and kind=%v is not a supported statically-sized kind", + dst.Type(), dst.Kind())) + } +} -- cgit v1.2.3-2-g168b