github.com/goccy/go-json@v0.10.3-0.20240509105655-5e2ae3f23c1d/internal/decoder/bytes.go (about) 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 }