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