Skip to content

Commit 89161f4

Browse files
author
yang.yu
committed
feat: add sizeof function
1 parent e6baf3f commit 89161f4

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

kaitai/sizefo.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package kaitai
2+
3+
import (
4+
"errors"
5+
"reflect"
6+
)
7+
8+
func SizeOf(msg interface{}) (uint64, error) {
9+
v := reflect.ValueOf(msg)
10+
return sizeof(v)
11+
}
12+
13+
func sizeof(fieldValue reflect.Value) (uint64, error) {
14+
switch fieldValue.Kind() {
15+
case reflect.Uint8, reflect.Int8, reflect.Bool:
16+
return 1, nil
17+
case reflect.Uint16, reflect.Int16:
18+
return 2, nil
19+
case reflect.Uint32, reflect.Int32, reflect.Float32:
20+
return 4, nil
21+
case reflect.Uint64, reflect.Int64, reflect.Float64:
22+
return 8, nil
23+
case reflect.String:
24+
return uint64(len(fieldValue.String())), nil
25+
case reflect.Slice, reflect.Array:
26+
arrLen := fieldValue.Len()
27+
var result uint64
28+
for i := 0; i < arrLen; i++ {
29+
v := fieldValue.Index(i)
30+
vl, err := sizeof(v)
31+
if err != nil {
32+
return 0, err
33+
}
34+
result += vl
35+
}
36+
return result, nil
37+
case reflect.Struct:
38+
numField := fieldValue.NumField()
39+
valueType := fieldValue.Type()
40+
var result uint64
41+
for i := 0; i < numField; i++ {
42+
fieldType := valueType.Field(i)
43+
// skip stream and not exported field
44+
if fieldType.Anonymous || fieldType.PkgPath != "" {
45+
continue
46+
}
47+
48+
v := fieldValue.Field(i)
49+
vl, err := sizeof(v)
50+
if err != nil {
51+
return 0, err
52+
}
53+
result += vl
54+
}
55+
return result, nil
56+
case reflect.Pointer:
57+
// nil 0
58+
if fieldValue.IsNil() {
59+
return 0, nil
60+
}
61+
fieldValue = fieldValue.Elem()
62+
return sizeof(fieldValue)
63+
case reflect.Interface:
64+
if fieldValue.IsNil() {
65+
return 0, errors.New(fieldValue.Kind().String() + " interface nil")
66+
}
67+
fieldValue = fieldValue.Elem()
68+
return sizeof(fieldValue)
69+
default:
70+
return 0, errors.New(`type "` + fieldValue.Kind().String() + `" not supported`)
71+
}
72+
}

kaitai/sizeof_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package kaitai
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestSizeOf(t *testing.T) {
8+
type args struct {
9+
*Stream
10+
Uint8 uint8
11+
Int8 int8
12+
Bool bool
13+
Uint16 uint16
14+
Int16 int16
15+
Uint32 uint32
16+
Int32 int32
17+
Float32 float32
18+
Uint64 uint64
19+
Int64 int64
20+
Float64 float64
21+
String string
22+
Bytes []byte
23+
Slice []string
24+
Array [4]byte
25+
Args *args
26+
}
27+
result := args{}
28+
var initLength uint64 = 55
29+
30+
l, err := SizeOf(result)
31+
if err != nil {
32+
t.Fatal(err)
33+
}
34+
if l == initLength {
35+
t.Fatal("wrong len")
36+
}
37+
result.String = "123"
38+
if l == initLength+3 {
39+
t.Fatal("wrong len")
40+
}
41+
result.Bytes = []byte("123")
42+
if l == initLength+6 {
43+
t.Fatal("wrong len")
44+
}
45+
result.Slice = []string{"1", "2"}
46+
if l == initLength+8 {
47+
t.Fatal("wrong len")
48+
}
49+
result.Args = &args{}
50+
if l == 2*initLength+8 {
51+
t.Fatal("wrong len")
52+
}
53+
}

0 commit comments

Comments
 (0)