github.com/night-codes/go-json@v0.9.15/internal/decoder/unmarshal_json.go (about)

     1  package decoder
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"unsafe"
     7  
     8  	"github.com/night-codes/go-json/internal/errors"
     9  	"github.com/night-codes/go-json/internal/runtime"
    10  )
    11  
    12  type unmarshalJSONDecoder struct {
    13  	typ        *runtime.Type
    14  	structName string
    15  	fieldName  string
    16  }
    17  
    18  func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
    19  	return &unmarshalJSONDecoder{
    20  		typ:        typ,
    21  		structName: structName,
    22  		fieldName:  fieldName,
    23  	}
    24  }
    25  
    26  func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
    27  	switch e := err.(type) {
    28  	case *errors.UnmarshalTypeError:
    29  		e.Struct = d.structName
    30  		e.Field = d.fieldName
    31  	case *errors.SyntaxError:
    32  		e.Offset = cursor
    33  	}
    34  }
    35  
    36  func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
    37  	s.skipWhiteSpace()
    38  	start := s.cursor
    39  	if err := s.skipValue(depth); err != nil {
    40  		return err
    41  	}
    42  	src := s.buf[start:s.cursor]
    43  	dst := make([]byte, len(src))
    44  	copy(dst, src)
    45  
    46  	v := *(*interface{})(unsafe.Pointer(&emptyInterface{
    47  		typ: d.typ,
    48  		ptr: p,
    49  	}))
    50  	switch v := v.(type) {
    51  	case unmarshalerContext:
    52  		var ctx context.Context
    53  		if (s.Option.Flags & ContextOption) != 0 {
    54  			ctx = s.Option.Context
    55  		} else {
    56  			ctx = context.Background()
    57  		}
    58  		if err := v.UnmarshalJSON(ctx, dst); err != nil {
    59  			d.annotateError(s.cursor, err)
    60  			return err
    61  		}
    62  	case json.Unmarshaler:
    63  		if err := v.UnmarshalJSON(dst); err != nil {
    64  			d.annotateError(s.cursor, err)
    65  			return err
    66  		}
    67  	}
    68  	return nil
    69  }
    70  
    71  func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
    72  	buf := ctx.Buf
    73  	cursor = skipWhiteSpace(buf, cursor)
    74  	start := cursor
    75  	end, err := skipValue(buf, cursor, depth)
    76  	if err != nil {
    77  		return 0, err
    78  	}
    79  	src := buf[start:end]
    80  	dst := make([]byte, len(src))
    81  	copy(dst, src)
    82  
    83  	v := *(*interface{})(unsafe.Pointer(&emptyInterface{
    84  		typ: d.typ,
    85  		ptr: p,
    86  	}))
    87  	if (ctx.Option.Flags & ContextOption) != 0 {
    88  		if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
    89  			d.annotateError(cursor, err)
    90  			return 0, err
    91  		}
    92  	} else {
    93  		if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
    94  			d.annotateError(cursor, err)
    95  			return 0, err
    96  		}
    97  	}
    98  	return end, nil
    99  }