/
reflect_array.go
114 lines (91 loc) · 2.45 KB
/
reflect_array.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
package bipf
import (
"errors"
"fmt"
"unsafe"
"github.com/modern-go/reflect2"
)
func decoderOfArray(ctx *ctx, typ reflect2.Type) (valDecoder, error) {
arrayType := typ.(*reflect2.UnsafeArrayType)
decoder, err := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
if err != nil {
return nil, err
}
return &arrayDecoder{arrayType, decoder}, nil
}
func encoderOfArray(ctx *ctx, typ reflect2.Type) (valEncoder, error) {
arrayType := typ.(*reflect2.UnsafeArrayType)
if arrayType.Len() == 0 {
return emptyArrayEncoder{}, nil
}
encoder, err := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem())
if err != nil {
return nil, err
}
return &arrayEncoder{arrayType, encoder}, nil
}
type emptyArrayEncoder struct{}
func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *stream) error {
stream.WriteEmptyArray()
return nil
}
func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) (bool, error) {
return true, nil
}
type arrayEncoder struct {
arrayType *reflect2.UnsafeArrayType
elemEncoder valEncoder
}
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *stream) error {
tmpStream := streamPool.BorrowStream(nil)
defer streamPool.ReturnStream(tmpStream)
for i := 0; i < encoder.arrayType.Len(); i++ {
elemPtr := encoder.arrayType.UnsafeGetIndex(ptr, i)
err := encoder.elemEncoder.Encode(elemPtr, tmpStream)
if err != nil {
return wrapf(err, "type '%v'", encoder.arrayType)
}
}
stream.WriteTag(uint64(tmpStream.Buffered()), valueTypeArray)
if _, err := stream.Write(tmpStream.Buffer()); err != nil {
return err
}
return nil
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) (bool, error) {
return false, nil
}
type arrayDecoder struct {
arrayType *reflect2.UnsafeArrayType
elemDecoder valDecoder
}
func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *iterator) error {
typ, l, err := iter.readTag()
if err != nil {
return nil
}
arrayType := decoder.arrayType
if typ == valueTypeBoolNull && l == 0 {
return nil
}
if typ != valueTypeArray {
return fmt.Errorf("incorrect type: %v", typ)
}
start := iter.numRead()
i := 0
for iter.numRead()-start < l {
if i >= arrayType.Len() {
return errors.New("provided array is too short")
}
elemPtr := arrayType.UnsafeGetIndex(ptr, i)
err := decoder.elemDecoder.Decode(elemPtr, iter)
if err != nil {
return err
}
if iter.numRead()-start > l {
return errors.New("out of bounds")
}
i++
}
return nil
}