github.com/3JoB/go-json@v0.10.4/decode.go (about)

     1  package json
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"unsafe"
     8  
     9  	"github.com/3JoB/go-reflect"
    10  
    11  	"github.com/3JoB/go-json/internal/decoder"
    12  	"github.com/3JoB/go-json/internal/errors"
    13  	"github.com/3JoB/go-json/internal/runtime"
    14  )
    15  
    16  type Decoder struct {
    17  	s *decoder.Stream
    18  }
    19  
    20  const (
    21  	nul = '\000'
    22  )
    23  
    24  type emptyInterface struct {
    25  	typ *runtime.Type
    26  	ptr unsafe.Pointer
    27  }
    28  
    29  func unmarshal(data []byte, v any, optFuncs ...DecodeOptionFunc) error {
    30  	src := make([]byte, len(data)+1) // append nul byte to the end
    31  	copy(src, data)
    32  
    33  	header := (*emptyInterface)(unsafe.Pointer(&v))
    34  
    35  	if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
    36  		return err
    37  	}
    38  	dec, err := decoder.CompileToGetDecoder(header.typ)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	ctx := decoder.TakeRuntimeContext()
    43  	ctx.Buf = src
    44  	ctx.Option.Flags = 0
    45  	for _, optFunc := range optFuncs {
    46  		optFunc(ctx.Option)
    47  	}
    48  	cursor, err := dec.Decode(ctx, 0, 0, header.ptr)
    49  	if err != nil {
    50  		decoder.ReleaseRuntimeContext(ctx)
    51  		return err
    52  	}
    53  	decoder.ReleaseRuntimeContext(ctx)
    54  	return validateEndBuf(src, cursor)
    55  }
    56  
    57  func unmarshalContext(ctx context.Context, data []byte, v any, optFuncs ...DecodeOptionFunc) error {
    58  	src := make([]byte, len(data)+1) // append nul byte to the end
    59  	copy(src, data)
    60  
    61  	header := (*emptyInterface)(unsafe.Pointer(&v))
    62  
    63  	if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
    64  		return err
    65  	}
    66  	dec, err := decoder.CompileToGetDecoder(header.typ)
    67  	if err != nil {
    68  		return err
    69  	}
    70  	rctx := decoder.TakeRuntimeContext()
    71  	rctx.Buf = src
    72  	rctx.Option.Flags = 0
    73  	rctx.Option.Flags |= decoder.ContextOption
    74  	rctx.Option.Context = ctx
    75  	for _, optFunc := range optFuncs {
    76  		optFunc(rctx.Option)
    77  	}
    78  	cursor, err := dec.Decode(rctx, 0, 0, header.ptr)
    79  	if err != nil {
    80  		decoder.ReleaseRuntimeContext(rctx)
    81  		return err
    82  	}
    83  	decoder.ReleaseRuntimeContext(rctx)
    84  	return validateEndBuf(src, cursor)
    85  }
    86  
    87  var (
    88  	pathDecoder = decoder.NewPathDecoder()
    89  )
    90  
    91  func extractFromPath(path *Path, data []byte, optFuncs ...DecodeOptionFunc) ([][]byte, error) {
    92  	if path.path.RootSelectorOnly {
    93  		return [][]byte{data}, nil
    94  	}
    95  	src := make([]byte, len(data)+1) // append nul byte to the end
    96  	copy(src, data)
    97  
    98  	ctx := decoder.TakeRuntimeContext()
    99  	ctx.Buf = src
   100  	ctx.Option.Flags = 0
   101  	ctx.Option.Flags |= decoder.PathOption
   102  	ctx.Option.Path = path.path
   103  	for _, optFunc := range optFuncs {
   104  		optFunc(ctx.Option)
   105  	}
   106  	paths, cursor, err := pathDecoder.DecodePath(ctx, 0, 0)
   107  	if err != nil {
   108  		decoder.ReleaseRuntimeContext(ctx)
   109  		return nil, err
   110  	}
   111  	decoder.ReleaseRuntimeContext(ctx)
   112  	if err := validateEndBuf(src, cursor); err != nil {
   113  		return nil, err
   114  	}
   115  	return paths, nil
   116  }
   117  
   118  func unmarshalNoEscape(data []byte, v any, optFuncs ...DecodeOptionFunc) error {
   119  	src := make([]byte, len(data)+1) // append nul byte to the end
   120  	copy(src, data)
   121  
   122  	header := (*emptyInterface)(unsafe.Pointer(&v))
   123  
   124  	if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
   125  		return err
   126  	}
   127  	dec, err := decoder.CompileToGetDecoder(header.typ)
   128  	if err != nil {
   129  		return err
   130  	}
   131  
   132  	ctx := decoder.TakeRuntimeContext()
   133  	ctx.Buf = src
   134  	ctx.Option.Flags = 0
   135  	for _, optFunc := range optFuncs {
   136  		optFunc(ctx.Option)
   137  	}
   138  	cursor, err := dec.Decode(ctx, 0, 0, noescape(header.ptr))
   139  	if err != nil {
   140  		decoder.ReleaseRuntimeContext(ctx)
   141  		return err
   142  	}
   143  	decoder.ReleaseRuntimeContext(ctx)
   144  	return validateEndBuf(src, cursor)
   145  }
   146  
   147  func validateEndBuf(src []byte, cursor int64) error {
   148  	for {
   149  		switch src[cursor] {
   150  		case ' ', '\t', '\n', '\r':
   151  			cursor++
   152  			continue
   153  		case nul:
   154  			return nil
   155  		}
   156  		return errors.ErrSyntax(
   157  			fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
   158  			cursor+1,
   159  		)
   160  	}
   161  }
   162  
   163  //nolint:staticcheck
   164  //go:nosplit
   165  func noescape(p unsafe.Pointer) unsafe.Pointer {
   166  	x := uintptr(p)
   167  	return unsafe.Pointer(x ^ 0)
   168  }
   169  
   170  func validateType(typ *runtime.Type, p uintptr) error {
   171  	if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
   172  		return &InvalidUnmarshalError{Type: reflect.ToT(runtime.RType2Type(typ))}
   173  	}
   174  	return nil
   175  }
   176  
   177  // NewDecoder returns a new decoder that reads from r.
   178  //
   179  // The decoder introduces its own buffering and may
   180  // read data from r beyond the JSON values requested.
   181  func NewDecoder(r io.Reader) *Decoder {
   182  	s := decoder.NewStream(r)
   183  	return &Decoder{
   184  		s: s,
   185  	}
   186  }
   187  
   188  // Buffered returns a reader of the data remaining in the Decoder's
   189  // buffer. The reader is valid until the next call to Decode.
   190  func (d *Decoder) Buffered() io.Reader {
   191  	return d.s.Buffered()
   192  }
   193  
   194  // Decode reads the next JSON-encoded value from its
   195  // input and stores it in the value pointed to by v.
   196  //
   197  // See the documentation for Unmarshal for details about
   198  // the conversion of JSON into a Go value.
   199  func (d *Decoder) Decode(v any) error {
   200  	return d.DecodeWithOption(v)
   201  }
   202  
   203  // DecodeContext reads the next JSON-encoded value from its
   204  // input and stores it in the value pointed to by v with context.Context.
   205  func (d *Decoder) DecodeContext(ctx context.Context, v any) error {
   206  	d.s.Option.Flags |= decoder.ContextOption
   207  	d.s.Option.Context = ctx
   208  	return d.DecodeWithOption(v)
   209  }
   210  
   211  func (d *Decoder) DecodeWithOption(v any, optFuncs ...DecodeOptionFunc) error {
   212  	header := (*emptyInterface)(unsafe.Pointer(&v))
   213  	typ := header.typ
   214  	ptr := uintptr(header.ptr)
   215  	typeptr := uintptr(unsafe.Pointer(typ))
   216  	// noescape trick for header.typ ( reflect.*rtype )
   217  	copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
   218  
   219  	if err := validateType(copiedType, ptr); err != nil {
   220  		return err
   221  	}
   222  
   223  	dec, err := decoder.CompileToGetDecoder(typ)
   224  	if err != nil {
   225  		return err
   226  	}
   227  	if err := d.s.PrepareForDecode(); err != nil {
   228  		return err
   229  	}
   230  	s := d.s
   231  	for _, optFunc := range optFuncs {
   232  		optFunc(s.Option)
   233  	}
   234  	if err := dec.DecodeStream(s, 0, header.ptr); err != nil {
   235  		d.s.SkipErrorValue()
   236  		return err
   237  	}
   238  	s.Reset()
   239  	return nil
   240  }
   241  
   242  func (d *Decoder) More() bool {
   243  	return d.s.More()
   244  }
   245  
   246  func (d *Decoder) Token() (Token, error) {
   247  	return d.s.Token()
   248  }
   249  
   250  // DisallowUnknownFields causes the Decoder to return an error when the destination
   251  // is a struct and the input contains object keys which do not match any
   252  // non-ignored, exported fields in the destination.
   253  func (d *Decoder) DisallowUnknownFields() {
   254  	d.s.DisallowUnknownFields = true
   255  }
   256  
   257  func (d *Decoder) InputOffset() int64 {
   258  	return d.s.TotalOffset()
   259  }
   260  
   261  // UseNumber causes the Decoder to unmarshal a number into an interface{} as a
   262  // Number instead of as a float64.
   263  func (d *Decoder) UseNumber() {
   264  	d.s.UseNumber = true
   265  }