-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvec.go
145 lines (136 loc) · 2.77 KB
/
vec.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package scale
import (
"bytes"
"errors"
)
type CompactVec struct {
Val []Compact
EleType PrimitiveType
}
func (c *CompactVec) Encode() ([]byte, error) {
if c.EleType == 0 {
return nil, errors.New("must point element type for vec")
}
l := getStringLenCompactType(len(c.Val))
if l == nil {
return nil, errors.New("vector length is too long")
}
var buf bytes.Buffer
lengthEncode, err := l.Encode()
if err != nil {
return nil, err
}
buf.Write(lengthEncode)
for _, v := range c.Val {
if v.GetType() != c.EleType {
return nil, errors.New("invalid vec")
}
res, err := v.Encode()
if err != nil {
return nil, err
}
buf.Write(res)
}
return buf.Bytes(), nil
}
func (c *CompactVec) Decode(value []byte) (int, error) {
if c.EleType == 0 {
return 0, errors.New("must point element type for vec")
}
ss := &CompactU128{}
offset, err := ss.Decode(value)
if err != nil {
return 0, err
}
if c.Val == nil {
c.Val = make([]Compact, ss.Val.Uint64())
}
value = value[offset:]
if ss.Val.Uint64() == 0 {
c.Clear()
}
for i := 0; i < int(ss.Val.Uint64()); i++ {
temp, err := c.getNextCompact()
if err != nil {
return 0, err
}
tempOffset, err := temp.Decode(value)
if err != nil {
return 0, err
}
if len(c.Val)-1 < i {
c.Val = append(c.Val, temp)
} else {
c.Val[i] = temp
}
offset += tempOffset
value = value[tempOffset:]
}
return offset, nil
}
func (c *CompactVec) GetVal() interface{} {
return c.Val
}
func (c *CompactVec) GetType() PrimitiveType {
return Vec
}
func (c *CompactVec) getNextCompact() (Compact, error) {
switch c.EleType {
case String:
return &CompactString{}, nil
case Uint8:
return &FixU8{}, nil
case Int8:
return &FixI8{}, nil
case CompactUInt8:
return &CompactU8{}, nil
case Uint16:
return &FixU16{}, nil
case Int16:
return &FixI16{}, nil
case CompactUint16:
return &CompactU16{}, nil
case Uint32:
return &FixU32{}, nil
case Int32:
return &FixI32{}, nil
case CompactUint32:
return &CompactU32{}, nil
case Uint64:
return &FixU64{}, nil
case Int64:
return &FixI64{}, nil
case CompactUint64:
return &CompactU64{}, nil
case BigInt:
return &FixI128{}, nil
case BigUint:
return &FixU128{}, nil
case CompactBigInt:
return &CompactU128{}, nil
case Bool:
return &CompactBool{}, nil
case Vec:
return c.Val[0].(*CompactVec).CloneNew(), nil
case Struct:
return c.Val[0].(*CompactStruct).CloneNew(), nil
case Array:
return c.Val[0].(*CompactArray).CloneNew(), nil
default:
return nil, errors.New("not supported type")
}
}
func (c *CompactVec) CloneNew() Compact {
temp := &CompactVec{
Val: nil,
EleType: 0,
}
temp.EleType = c.EleType
for _, v := range c.Val {
temp.Val = append(temp.Val, v.CloneNew())
}
return temp
}
func (c *CompactVec) Clear() {
c.Val = nil
}