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

     1  package decoder
     2  
     3  import (
     4  	"bytes"
     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 funcDecoder struct {
    12  	typ        *runtime.Type
    13  	structName string
    14  	fieldName  string
    15  }
    16  
    17  func newFuncDecoder(typ *runtime.Type, structName, fieldName string) *funcDecoder {
    18  	fnDecoder := &funcDecoder{typ, structName, fieldName}
    19  	return fnDecoder
    20  }
    21  
    22  func (d *funcDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
    23  	s.skipWhiteSpace()
    24  	start := s.cursor
    25  	if err := s.skipValue(depth); err != nil {
    26  		return err
    27  	}
    28  	src := s.buf[start:s.cursor]
    29  	if len(src) > 0 {
    30  		switch src[0] {
    31  		case '"':
    32  			return &errors.UnmarshalTypeError{
    33  				Value:  "string",
    34  				Type:   runtime.RType2Type(d.typ),
    35  				Offset: s.totalOffset(),
    36  			}
    37  		case '[':
    38  			return &errors.UnmarshalTypeError{
    39  				Value:  "array",
    40  				Type:   runtime.RType2Type(d.typ),
    41  				Offset: s.totalOffset(),
    42  			}
    43  		case '{':
    44  			return &errors.UnmarshalTypeError{
    45  				Value:  "object",
    46  				Type:   runtime.RType2Type(d.typ),
    47  				Offset: s.totalOffset(),
    48  			}
    49  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
    50  			return &errors.UnmarshalTypeError{
    51  				Value:  "number",
    52  				Type:   runtime.RType2Type(d.typ),
    53  				Offset: s.totalOffset(),
    54  			}
    55  		case 'n':
    56  			if err := nullBytes(s); err != nil {
    57  				return err
    58  			}
    59  			*(*unsafe.Pointer)(p) = nil
    60  			return nil
    61  		case 't':
    62  			if err := trueBytes(s); err == nil {
    63  				return &errors.UnmarshalTypeError{
    64  					Value:  "boolean",
    65  					Type:   runtime.RType2Type(d.typ),
    66  					Offset: s.totalOffset(),
    67  				}
    68  			}
    69  		case 'f':
    70  			if err := falseBytes(s); err == nil {
    71  				return &errors.UnmarshalTypeError{
    72  					Value:  "boolean",
    73  					Type:   runtime.RType2Type(d.typ),
    74  					Offset: s.totalOffset(),
    75  				}
    76  			}
    77  		}
    78  	}
    79  	return errors.ErrInvalidBeginningOfValue(s.buf[s.cursor], s.totalOffset())
    80  }
    81  
    82  func (d *funcDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
    83  	buf := ctx.Buf
    84  	cursor = skipWhiteSpace(buf, cursor)
    85  	start := cursor
    86  	end, err := skipValue(buf, cursor, depth)
    87  	if err != nil {
    88  		return 0, err
    89  	}
    90  	src := buf[start:end]
    91  	if len(src) > 0 {
    92  		switch src[0] {
    93  		case '"':
    94  			return 0, &errors.UnmarshalTypeError{
    95  				Value:  "string",
    96  				Type:   runtime.RType2Type(d.typ),
    97  				Offset: start,
    98  			}
    99  		case '[':
   100  			return 0, &errors.UnmarshalTypeError{
   101  				Value:  "array",
   102  				Type:   runtime.RType2Type(d.typ),
   103  				Offset: start,
   104  			}
   105  		case '{':
   106  			return 0, &errors.UnmarshalTypeError{
   107  				Value:  "object",
   108  				Type:   runtime.RType2Type(d.typ),
   109  				Offset: start,
   110  			}
   111  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   112  			return 0, &errors.UnmarshalTypeError{
   113  				Value:  "number",
   114  				Type:   runtime.RType2Type(d.typ),
   115  				Offset: start,
   116  			}
   117  		case 'n':
   118  			if bytes.Equal(src, nullbytes) {
   119  				*(*unsafe.Pointer)(p) = nil
   120  				return end, nil
   121  			}
   122  		case 't':
   123  			if err := validateTrue(buf, start); err == nil {
   124  				return 0, &errors.UnmarshalTypeError{
   125  					Value:  "boolean",
   126  					Type:   runtime.RType2Type(d.typ),
   127  					Offset: start,
   128  				}
   129  			}
   130  		case 'f':
   131  			if err := validateFalse(buf, start); err == nil {
   132  				return 0, &errors.UnmarshalTypeError{
   133  					Value:  "boolean",
   134  					Type:   runtime.RType2Type(d.typ),
   135  					Offset: start,
   136  				}
   137  			}
   138  		}
   139  	}
   140  	return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
   141  }