1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
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, dstPtr interface{}) error {
_dstPtr := reflect.ValueOf(dstPtr)
if _dstPtr.Kind() != reflect.Ptr {
return fmt.Errorf("not a pointer: %v", _dstPtr.Type())
}
dst := _dstPtr.Elem()
handler, err := getHandler(dst.Type())
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.Set(reflect.ValueOf(val).Convert(dst.Type()))
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
}
|