summaryrefslogtreecommitdiff
path: root/lib/binstruct/marshal.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/binstruct/marshal.go')
-rw-r--r--lib/binstruct/marshal.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/lib/binstruct/marshal.go b/lib/binstruct/marshal.go
new file mode 100644
index 0000000..684d2f3
--- /dev/null
+++ b/lib/binstruct/marshal.go
@@ -0,0 +1,42 @@
+package binstruct
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+)
+
+type Marshaler = encoding.BinaryMarshaler
+
+func Marshal(obj any) ([]byte, error) {
+ if mar, ok := obj.(Marshaler); ok {
+ return mar.MarshalBinary()
+ }
+ return MarshalWithoutInterface(obj)
+}
+
+func MarshalWithoutInterface(obj any) ([]byte, error) {
+ val := reflect.ValueOf(obj)
+ switch val.Kind() {
+ case reflect.Uint8, reflect.Int8, reflect.Uint16, reflect.Int16, reflect.Uint32, reflect.Int32, reflect.Uint64, reflect.Int64:
+ typ := intKind2Type[val.Kind()]
+ return val.Convert(typ).Interface().(Marshaler).MarshalBinary()
+ case reflect.Ptr:
+ return Marshal(val.Elem().Interface())
+ case reflect.Array:
+ var ret []byte
+ for i := 0; i < val.Len(); i++ {
+ bs, err := Marshal(val.Index(i).Interface())
+ ret = append(ret, bs...)
+ if err != nil {
+ return ret, err
+ }
+ }
+ return ret, nil
+ case reflect.Struct:
+ return getStructHandler(val.Type()).Marshal(val)
+ default:
+ panic(fmt.Errorf("type=%v does not implement binfmt.Marshaler and kind=%v is not a supported statically-sized kind",
+ val.Type(), val.Kind()))
+ }
+}