github.com/3JoB/go-json@v0.10.4/internal/decoder/bytes.go (about)

     1  package decoder
     2  
     3  import (
     4  	"encoding/base64"
     5  	"unsafe"
     6  
     7  	"github.com/3JoB/go-json/internal/errors"
     8  	"github.com/3JoB/go-json/internal/runtime"
     9  	"github.com/3JoB/go-reflect"
    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(reflect.ToRT(unmarshalJSONType)):
    24  		unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
    25  	case runtime.PtrTo(typ).Implements(reflect.ToRT(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, errors.New("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:   reflect.ToT(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:   reflect.ToT(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  }