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  }