diff options
Diffstat (limited to 'pkg/binstruct/unmarshal.go')
-rw-r--r-- | pkg/binstruct/unmarshal.go | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/pkg/binstruct/unmarshal.go b/pkg/binstruct/unmarshal.go new file mode 100644 index 0000000..4810d78 --- /dev/null +++ b/pkg/binstruct/unmarshal.go @@ -0,0 +1,44 @@ +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) + } + _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.Ptr: + elemPtr := reflect.New(dst.Type().Elem()).Interface() + n, err := Unmarshal(dat, elemPtr) + 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: + // TODO + default: + panic(fmt.Errorf("type=%v does not implement binfmt.Unmarshaler and kind=%v is not a supported statically-sized kind", + val.Type(), val.Kind())) + } +} |