diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-05-10 03:59:33 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-05-10 03:59:33 -0600 |
commit | a16049ef805c0c08b90885a5b7dfea7f74e51c5f (patch) | |
tree | 5b5dad8b0d44ccd3e7a43ac5bde557ae220a0f04 /pkg/binstruct/l3.go |
initial commit
Diffstat (limited to 'pkg/binstruct/l3.go')
-rw-r--r-- | pkg/binstruct/l3.go | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/pkg/binstruct/l3.go b/pkg/binstruct/l3.go new file mode 100644 index 0000000..f9fb8b1 --- /dev/null +++ b/pkg/binstruct/l3.go @@ -0,0 +1,61 @@ +package binstruct + +import ( + "fmt" + "reflect" +) + +var handlerCache = make(map[reflect.Type]handler) + +func getHandler(typ reflect.Type) (handler, error) { + h, ok := handlerCache[typ] + if ok { + return h, nil + } + + h, err := genHandler(typ) + if err != nil { + return nil, err + } + handlerCache[typ] = h + return h, nil +} + +func Unmarshal(dat []byte, dst interface{}) error { + _dst := reflect.ValueOf(dst) + if _dst.Kind() != reflect.Ptr { + return fmt.Errorf("not a pointer: %v", _dst.Type()) + } + handler, err := getHandler(_dst.Type().Elem()) + if err != nil { + return err + } + if int64(len(dat)) < handler.Size() { + return fmt.Errorf("need at least %d bytes of data, only have %d", + handler.Size(), len(dat)) + } + val := handler.Unmarshal(dat[:handler.Size()]) + _dst.Elem().Set(reflect.ValueOf(val)) + return nil +} + +func Marshal(val interface{}) ([]byte, error) { + handler, err := getHandler(reflect.TypeOf(val)) + if err != nil { + return nil, err + } + bs := handler.Marshal(val) + if int64(len(bs)) != handler.Size() { + return nil, fmt.Errorf("got %d bytes but expected %d bytes", + len(bs), handler.Size()) + } + return bs, nil +} + +func Size(val interface{}) (int64, error) { + handler, err := getHandler(reflect.TypeOf(val)) + if err != nil { + return 0, err + } + return handler.Size(), nil +} |