1 package decoder
2
3 import (
4 "encoding/base64"
5 "fmt"
6 "unsafe"
7
8 "github.com/goccy/go-json/internal/errors"
9 "github.com/goccy/go-json/internal/runtime"
10 )
11
12 type bytesDecoder struct {
13 typ *runtime.Type
14 sliceDecoder Decoder
15 stringDecoder *stringDecoder
16 structName string
17 fieldName string
18 }
19
20 func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder {
21 var unmarshalDecoder Decoder
22 switch {
23 case runtime.PtrTo(typ).Implements(unmarshalJSONType):
24 unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
25 case runtime.PtrTo(typ).Implements(unmarshalTextType):
26 unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
27 default:
28 unmarshalDecoder, _ = compileUint8(typ, structName, fieldName)
29 }
30 return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
31 }
32
33 func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder {
34 return &bytesDecoder{
35 typ: typ,
36 sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
37 stringDecoder: newStringDecoder(structName, fieldName),
38 structName: structName,
39 fieldName: fieldName,
40 }
41 }
42
43 func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
44 bytes, err := d.decodeStreamBinary(s, depth, p)
45 if err != nil {
46 return err
47 }
48 if bytes == nil {
49 s.reset()
50 return nil
51 }
52 decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
53 buf := make([]byte, decodedLen)
54 n, err := base64.StdEncoding.Decode(buf, bytes)
55 if err != nil {
56 return err
57 }
58 *(*[]byte)(p) = buf[:n]
59 s.reset()
60 return nil
61 }
62
63 func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
64 bytes, c, err := d.decodeBinary(ctx, cursor, depth, p)
65 if err != nil {
66 return 0, err
67 }
68 if bytes == nil {
69 return c, nil
70 }
71 cursor = c
72 decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
73 b := make([]byte, decodedLen)
74 n, err := base64.StdEncoding.Decode(b, bytes)
75 if err != nil {
76 return 0, err
77 }
78 *(*[]byte)(p) = b[:n]
79 return cursor, nil
80 }
81
82 func (d *bytesDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
83 return nil, 0, fmt.Errorf("json: []byte decoder does not support decode path")
84 }
85
86 func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
87 c := s.skipWhiteSpace()
88 if c == '[' {
89 if d.sliceDecoder == nil {
90 return nil, &errors.UnmarshalTypeError{
91 Type: runtime.RType2Type(d.typ),
92 Offset: s.totalOffset(),
93 }
94 }
95 err := d.sliceDecoder.DecodeStream(s, depth, p)
96 return nil, err
97 }
98 return d.stringDecoder.decodeStreamByte(s)
99 }
100
101 func (d *bytesDecoder) decodeBinary(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
102 buf := ctx.Buf
103 cursor = skipWhiteSpace(buf, cursor)
104 if buf[cursor] == '[' {
105 if d.sliceDecoder == nil {
106 return nil, 0, &errors.UnmarshalTypeError{
107 Type: runtime.RType2Type(d.typ),
108 Offset: cursor,
109 }
110 }
111 c, err := d.sliceDecoder.Decode(ctx, cursor, depth, p)
112 if err != nil {
113 return nil, 0, err
114 }
115 return nil, c, nil
116 }
117 return d.stringDecoder.decodeByte(buf, cursor)
118 }
119
View as plain text