github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/decoder/decoder.go (about)

     1  /*
     2   * Copyright 2021 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package decoder
    18  
    19  import (
    20  	"encoding/json"
    21  	"reflect"
    22  	"runtime"
    23  	"unsafe"
    24  
    25  	"github.com/goshafaq/sonic/internal/native"
    26  	"github.com/goshafaq/sonic/internal/native/types"
    27  	"github.com/goshafaq/sonic/internal/rt"
    28  	"github.com/goshafaq/sonic/option"
    29  	"github.com/goshafaq/sonic/utf8"
    30  )
    31  
    32  const (
    33  	_F_use_int64       = 0
    34  	_F_disable_urc     = 2
    35  	_F_disable_unknown = 3
    36  	_F_copy_string     = 4
    37  
    38  	_F_use_number      = types.B_USE_NUMBER
    39  	_F_validate_string = types.B_VALIDATE_STRING
    40  	_F_allow_control   = types.B_ALLOW_CONTROL
    41  )
    42  
    43  type Options uint64
    44  
    45  const (
    46  	OptionUseInt64         Options = 1 << _F_use_int64
    47  	OptionUseNumber        Options = 1 << _F_use_number
    48  	OptionUseUnicodeErrors Options = 1 << _F_disable_urc
    49  	OptionDisableUnknown   Options = 1 << _F_disable_unknown
    50  	OptionCopyString       Options = 1 << _F_copy_string
    51  	OptionValidateString   Options = 1 << _F_validate_string
    52  )
    53  
    54  func (self *Decoder) SetOptions(opts Options) {
    55  	if (opts&OptionUseNumber != 0) && (opts&OptionUseInt64 != 0) {
    56  		panic("can't set OptionUseInt64 and OptionUseNumber both!")
    57  	}
    58  	self.f = uint64(opts)
    59  }
    60  
    61  // Decoder is the decoder context object
    62  type Decoder struct {
    63  	i int
    64  	f uint64
    65  	s string
    66  }
    67  
    68  // NewDecoder creates a new decoder instance.
    69  func NewDecoder(s string) *Decoder {
    70  	return &Decoder{s: s}
    71  }
    72  
    73  // Pos returns the current decoding position.
    74  func (self *Decoder) Pos() int {
    75  	return self.i
    76  }
    77  
    78  func (self *Decoder) Reset(s string) {
    79  	self.s = s
    80  	self.i = 0
    81  	// self.f = 0
    82  }
    83  
    84  func (self *Decoder) CheckTrailings() error {
    85  	pos := self.i
    86  	buf := self.s
    87  	/* skip all the trailing spaces */
    88  	if pos != len(buf) {
    89  		for pos < len(buf) && (types.SPACE_MASK&(1<<buf[pos])) != 0 {
    90  			pos++
    91  		}
    92  	}
    93  
    94  	/* then it must be at EOF */
    95  	if pos == len(buf) {
    96  		return nil
    97  	}
    98  
    99  	/* junk after JSON value */
   100  	return SyntaxError{
   101  		Src:  buf,
   102  		Pos:  pos,
   103  		Code: types.ERR_INVALID_CHAR,
   104  	}
   105  }
   106  
   107  // Decode parses the JSON-encoded data from current position and stores the result
   108  // in the value pointed to by val.
   109  func (self *Decoder) Decode(val interface{}) error {
   110  	/* validate json if needed */
   111  	if (self.f&(1<<_F_validate_string)) != 0 && !utf8.ValidateString(self.s) {
   112  		dbuf := utf8.CorrectWith(nil, rt.Str2Mem(self.s), "\ufffd")
   113  		self.s = rt.Mem2Str(dbuf)
   114  	}
   115  
   116  	vv := rt.UnpackEface(val)
   117  	vp := vv.Value
   118  
   119  	/* check for nil type */
   120  	if vv.Type == nil {
   121  		return &json.InvalidUnmarshalError{}
   122  	}
   123  
   124  	/* must be a non-nil pointer */
   125  	if vp == nil || vv.Type.Kind() != reflect.Ptr {
   126  		return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}
   127  	}
   128  
   129  	etp := rt.PtrElem(vv.Type)
   130  
   131  	/* check the defined pointer type for issue 379 */
   132  	if vv.Type.IsNamed() {
   133  		newp := vp
   134  		etp = vv.Type
   135  		vp = unsafe.Pointer(&newp)
   136  	}
   137  
   138  	/* create a new stack, and call the decoder */
   139  	sb := newStack()
   140  	nb, err := decodeTypedPointer(self.s, self.i, etp, vp, sb, self.f)
   141  	/* return the stack back */
   142  	self.i = nb
   143  	freeStack(sb)
   144  
   145  	/* avoid GC ahead */
   146  	runtime.KeepAlive(vv)
   147  	return err
   148  }
   149  
   150  // UseInt64 indicates the Decoder to unmarshal an integer into an interface{} as an
   151  // int64 instead of as a float64.
   152  func (self *Decoder) UseInt64() {
   153  	self.f |= 1 << _F_use_int64
   154  	self.f &^= 1 << _F_use_number
   155  }
   156  
   157  // UseNumber indicates the Decoder to unmarshal a number into an interface{} as a
   158  // json.Number instead of as a float64.
   159  func (self *Decoder) UseNumber() {
   160  	self.f &^= 1 << _F_use_int64
   161  	self.f |= 1 << _F_use_number
   162  }
   163  
   164  // UseUnicodeErrors indicates the Decoder to return an error when encounter invalid
   165  // UTF-8 escape sequences.
   166  func (self *Decoder) UseUnicodeErrors() {
   167  	self.f |= 1 << _F_disable_urc
   168  }
   169  
   170  // DisallowUnknownFields indicates the Decoder to return an error when the destination
   171  // is a struct and the input contains object keys which do not match any
   172  // non-ignored, exported fields in the destination.
   173  func (self *Decoder) DisallowUnknownFields() {
   174  	self.f |= 1 << _F_disable_unknown
   175  }
   176  
   177  // CopyString indicates the Decoder to decode string values by copying instead of referring.
   178  func (self *Decoder) CopyString() {
   179  	self.f |= 1 << _F_copy_string
   180  }
   181  
   182  // ValidateString causes the Decoder to validate string values when decoding string value
   183  // in JSON. Validation is that, returning error when unescaped control chars(0x00-0x1f) or
   184  // invalid UTF-8 chars in the string value of JSON.
   185  func (self *Decoder) ValidateString() {
   186  	self.f |= 1 << _F_validate_string
   187  }
   188  
   189  // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
   190  // order to reduce the first-hit latency.
   191  //
   192  // Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
   193  // a compile option to set the depth of recursive compile for the nested struct type.
   194  func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
   195  	cfg := option.DefaultCompileOptions()
   196  	for _, opt := range opts {
   197  		opt(&cfg)
   198  	}
   199  	return pretouchRec(map[reflect.Type]bool{vt: true}, cfg)
   200  }
   201  
   202  func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {
   203  	/* compile function */
   204  	compiler := newCompiler().apply(opts)
   205  	decoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
   206  		if pp, err := compiler.compile(_vt); err != nil {
   207  			return nil, err
   208  		} else {
   209  			as := newAssembler(pp)
   210  			as.name = _vt.String()
   211  			return as.Load(), nil
   212  		}
   213  	}
   214  
   215  	/* find or compile */
   216  	vt := rt.UnpackType(_vt)
   217  	if val := programCache.Get(vt); val != nil {
   218  		return nil, nil
   219  	} else if _, err := programCache.Compute(vt, decoder); err == nil {
   220  		return compiler.rec, nil
   221  	} else {
   222  		return nil, err
   223  	}
   224  }
   225  
   226  func pretouchRec(vtm map[reflect.Type]bool, opts option.CompileOptions) error {
   227  	if opts.RecursiveDepth < 0 || len(vtm) == 0 {
   228  		return nil
   229  	}
   230  	next := make(map[reflect.Type]bool)
   231  	for vt := range vtm {
   232  		sub, err := pretouchType(vt, opts)
   233  		if err != nil {
   234  			return err
   235  		}
   236  		for svt := range sub {
   237  			next[svt] = true
   238  		}
   239  	}
   240  	opts.RecursiveDepth -= 1
   241  	return pretouchRec(next, opts)
   242  }
   243  
   244  // Skip skips only one json value, and returns first non-blank character position and its ending position if it is valid.
   245  // Otherwise, returns negative error code using start and invalid character position using end
   246  func Skip(data []byte) (start int, end int) {
   247  	s := rt.Mem2Str(data)
   248  	p := 0
   249  	m := types.NewStateMachine()
   250  	ret := native.SkipOne(&s, &p, m, uint64(0))
   251  	types.FreeStateMachine(m)
   252  	return ret, p
   253  }