diff options
Diffstat (limited to 'vendor/github.com/json-iterator/go/reflect_slice.go')
-rw-r--r-- | vendor/github.com/json-iterator/go/reflect_slice.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/vendor/github.com/json-iterator/go/reflect_slice.go b/vendor/github.com/json-iterator/go/reflect_slice.go new file mode 100644 index 0000000..9441d79 --- /dev/null +++ b/vendor/github.com/json-iterator/go/reflect_slice.go | |||
@@ -0,0 +1,99 @@ | |||
1 | package jsoniter | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "github.com/modern-go/reflect2" | ||
6 | "io" | ||
7 | "unsafe" | ||
8 | ) | ||
9 | |||
10 | func decoderOfSlice(ctx *ctx, typ reflect2.Type) ValDecoder { | ||
11 | sliceType := typ.(*reflect2.UnsafeSliceType) | ||
12 | decoder := decoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) | ||
13 | return &sliceDecoder{sliceType, decoder} | ||
14 | } | ||
15 | |||
16 | func encoderOfSlice(ctx *ctx, typ reflect2.Type) ValEncoder { | ||
17 | sliceType := typ.(*reflect2.UnsafeSliceType) | ||
18 | encoder := encoderOfType(ctx.append("[sliceElem]"), sliceType.Elem()) | ||
19 | return &sliceEncoder{sliceType, encoder} | ||
20 | } | ||
21 | |||
22 | type sliceEncoder struct { | ||
23 | sliceType *reflect2.UnsafeSliceType | ||
24 | elemEncoder ValEncoder | ||
25 | } | ||
26 | |||
27 | func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { | ||
28 | if encoder.sliceType.UnsafeIsNil(ptr) { | ||
29 | stream.WriteNil() | ||
30 | return | ||
31 | } | ||
32 | length := encoder.sliceType.UnsafeLengthOf(ptr) | ||
33 | if length == 0 { | ||
34 | stream.WriteEmptyArray() | ||
35 | return | ||
36 | } | ||
37 | stream.WriteArrayStart() | ||
38 | encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream) | ||
39 | for i := 1; i < length; i++ { | ||
40 | stream.WriteMore() | ||
41 | elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i) | ||
42 | encoder.elemEncoder.Encode(elemPtr, stream) | ||
43 | } | ||
44 | stream.WriteArrayEnd() | ||
45 | if stream.Error != nil && stream.Error != io.EOF { | ||
46 | stream.Error = fmt.Errorf("%v: %s", encoder.sliceType, stream.Error.Error()) | ||
47 | } | ||
48 | } | ||
49 | |||
50 | func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool { | ||
51 | return encoder.sliceType.UnsafeLengthOf(ptr) == 0 | ||
52 | } | ||
53 | |||
54 | type sliceDecoder struct { | ||
55 | sliceType *reflect2.UnsafeSliceType | ||
56 | elemDecoder ValDecoder | ||
57 | } | ||
58 | |||
59 | func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { | ||
60 | decoder.doDecode(ptr, iter) | ||
61 | if iter.Error != nil && iter.Error != io.EOF { | ||
62 | iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error()) | ||
63 | } | ||
64 | } | ||
65 | |||
66 | func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { | ||
67 | c := iter.nextToken() | ||
68 | sliceType := decoder.sliceType | ||
69 | if c == 'n' { | ||
70 | iter.skipThreeBytes('u', 'l', 'l') | ||
71 | sliceType.UnsafeSetNil(ptr) | ||
72 | return | ||
73 | } | ||
74 | if c != '[' { | ||
75 | iter.ReportError("decode slice", "expect [ or n, but found "+string([]byte{c})) | ||
76 | return | ||
77 | } | ||
78 | c = iter.nextToken() | ||
79 | if c == ']' { | ||
80 | sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0)) | ||
81 | return | ||
82 | } | ||
83 | iter.unreadByte() | ||
84 | sliceType.UnsafeGrow(ptr, 1) | ||
85 | elemPtr := sliceType.UnsafeGetIndex(ptr, 0) | ||
86 | decoder.elemDecoder.Decode(elemPtr, iter) | ||
87 | length := 1 | ||
88 | for c = iter.nextToken(); c == ','; c = iter.nextToken() { | ||
89 | idx := length | ||
90 | length += 1 | ||
91 | sliceType.UnsafeGrow(ptr, length) | ||
92 | elemPtr = sliceType.UnsafeGetIndex(ptr, idx) | ||
93 | decoder.elemDecoder.Decode(elemPtr, iter) | ||
94 | } | ||
95 | if c != ']' { | ||
96 | iter.ReportError("decode slice", "expect ], but found "+string([]byte{c})) | ||
97 | return | ||
98 | } | ||
99 | } | ||