-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathbinary_size.go
65 lines (51 loc) · 1.14 KB
/
binary_size.go
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
64
65
package goobjfmt
import (
"reflect"
)
func dataSize(v reflect.Value, sf *reflect.StructField) int {
switch v.Kind() {
case reflect.Array:
if s := dataSize(v.Elem(), nil); s >= 0 {
return s*v.Type().Len() + 4
}
case reflect.Slice:
l := v.Len()
elemSize := int(v.Type().Elem().Size())
return l*elemSize + 2
case reflect.String:
t := v.Len()
return t + 2
case reflect.Bool,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Float32, reflect.Float64:
return int(v.Type().Size())
case reflect.Struct:
sum := 0
st := v.Type()
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
sf := st.Field(i)
s := dataSize(fv, &sf)
if s < 0 {
return -1
}
sum += s
}
return sum
case reflect.Int:
panic("do not support int, use int32/int64 instead")
return 0
default:
if sf != nil && sf.Tag.Get("binary") == "-" {
return 0
} else {
panic("size: unsupport kind: " + v.Kind().String())
}
}
return -1
}
func BinarySize(obj interface{}) int {
v := reflect.Indirect(reflect.ValueOf(obj))
return dataSize(v, nil)
}