github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/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      `unsafe`
    21      `encoding/json`
    22      `reflect`
    23      `runtime`
    24  
    25      `github.com/bytedance/sonic/internal/native`
    26      `github.com/bytedance/sonic/internal/native/types`
    27      `github.com/bytedance/sonic/internal/rt`
    28      `github.com/bytedance/sonic/option`
    29      `github.com/bytedance/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  
    62  // Decoder is the decoder context object
    63  type Decoder struct {
    64      i int
    65      f uint64
    66      s string
    67  }
    68  
    69  // NewDecoder creates a new decoder instance.
    70  func NewDecoder(s string) *Decoder {
    71      return &Decoder{s: s}
    72  }
    73  
    74  // Pos returns the current decoding position.
    75  func (self *Decoder) Pos() int {
    76      return self.i
    77  }
    78  
    79  func (self *Decoder) Reset(s string) {
    80      self.s = s
    81      self.i = 0
    82      // self.f = 0
    83  }
    84  
    85  func (self *Decoder) CheckTrailings() error {
    86      pos := self.i
    87      buf := self.s
    88      /* skip all the trailing spaces */
    89      if pos != len(buf) {
    90          for pos < len(buf) && (types.SPACE_MASK & (1 << buf[pos])) != 0 {
    91              pos++
    92          }
    93      }
    94  
    95      /* then it must be at EOF */
    96      if pos == len(buf) {
    97          return nil
    98      }
    99  
   100      /* junk after JSON value */
   101      return SyntaxError {
   102          Src  : buf,
   103          Pos  : pos,
   104          Code : types.ERR_INVALID_CHAR,
   105      }
   106  }
   107  
   108  
   109  // Decode parses the JSON-encoded data from current position and stores the result
   110  // in the value pointed to by val.
   111  func (self *Decoder) Decode(val interface{}) error {
   112      /* validate json if needed */
   113      if (self.f & (1 << _F_validate_string)) != 0  && !utf8.ValidateString(self.s){
   114          dbuf := utf8.CorrectWith(nil, rt.Str2Mem(self.s), "\ufffd")
   115          self.s = rt.Mem2Str(dbuf)
   116      }
   117  
   118      vv := rt.UnpackEface(val)
   119      vp := vv.Value
   120  
   121      /* check for nil type */
   122      if vv.Type == nil {
   123          return &json.InvalidUnmarshalError{}
   124      }
   125  
   126      /* must be a non-nil pointer */
   127      if vp == nil || vv.Type.Kind() != reflect.Ptr {
   128          return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}
   129      }
   130  
   131      etp := rt.PtrElem(vv.Type)
   132  
   133      /* check the defined pointer type for issue 379 */
   134      if vv.Type.IsNamed() {
   135          newp := vp
   136          etp  = vv.Type
   137          vp   = unsafe.Pointer(&newp)
   138      }
   139  
   140      /* create a new stack, and call the decoder */
   141      sb := newStack()
   142      nb, err := decodeTypedPointer(self.s, self.i, etp, vp, sb, self.f)
   143      /* return the stack back */
   144      self.i = nb
   145      freeStack(sb)
   146  
   147      /* avoid GC ahead */
   148      runtime.KeepAlive(vv)
   149      return err
   150  }
   151  
   152  // UseInt64 indicates the Decoder to unmarshal an integer into an interface{} as an
   153  // int64 instead of as a float64.
   154  func (self *Decoder) UseInt64() {
   155      self.f  |= 1 << _F_use_int64
   156      self.f &^= 1 << _F_use_number
   157  }
   158  
   159  // UseNumber indicates the Decoder to unmarshal a number into an interface{} as a
   160  // json.Number instead of as a float64.
   161  func (self *Decoder) UseNumber() {
   162      self.f &^= 1 << _F_use_int64
   163      self.f  |= 1 << _F_use_number
   164  }
   165  
   166  // UseUnicodeErrors indicates the Decoder to return an error when encounter invalid
   167  // UTF-8 escape sequences.
   168  func (self *Decoder) UseUnicodeErrors() {
   169      self.f |= 1 << _F_disable_urc
   170  }
   171  
   172  // DisallowUnknownFields indicates the Decoder to return an error when the destination
   173  // is a struct and the input contains object keys which do not match any
   174  // non-ignored, exported fields in the destination.
   175  func (self *Decoder) DisallowUnknownFields() {
   176      self.f |= 1 << _F_disable_unknown
   177  }
   178  
   179  // CopyString indicates the Decoder to decode string values by copying instead of referring.
   180  func (self *Decoder) CopyString() {
   181      self.f |= 1 << _F_copy_string
   182  }
   183  
   184  // ValidateString causes the Decoder to validate string values when decoding string value 
   185  // in JSON. Validation is that, returning error when unescaped control chars(0x00-0x1f) or
   186  // invalid UTF-8 chars in the string value of JSON.
   187  func (self *Decoder) ValidateString() {
   188      self.f |= 1 << _F_validate_string
   189  }
   190  
   191  // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
   192  // order to reduce the first-hit latency.
   193  //
   194  // Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
   195  // a compile option to set the depth of recursive compile for the nested struct type.
   196  func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
   197      cfg := option.DefaultCompileOptions()
   198      for _, opt := range opts {
   199          opt(&cfg)
   200      }
   201      return pretouchRec(map[reflect.Type]bool{vt:true}, cfg)
   202  }
   203  
   204  func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {
   205      /* compile function */
   206      compiler := newCompiler().apply(opts)
   207      decoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
   208          if pp, err := compiler.compile(_vt); err != nil {
   209              return nil, err
   210          } else {
   211              as := newAssembler(pp)
   212              as.name = _vt.String()
   213              return as.Load(), nil
   214          }
   215      }
   216  
   217      /* find or compile */
   218      vt := rt.UnpackType(_vt)
   219      if val := programCache.Get(vt); val != nil {
   220          return nil, nil
   221      } else if _, err := programCache.Compute(vt, decoder); err == nil {
   222          return compiler.rec, nil
   223      } else {
   224          return nil, err
   225      }
   226  }
   227  
   228  func pretouchRec(vtm map[reflect.Type]bool, opts option.CompileOptions) error {
   229      if opts.RecursiveDepth < 0 || len(vtm) == 0 {
   230          return nil
   231      }
   232      next := make(map[reflect.Type]bool)
   233      for vt := range(vtm) {
   234          sub, err := pretouchType(vt, opts)
   235          if err != nil {
   236              return err
   237          }
   238          for svt := range(sub) {
   239              next[svt] = true
   240          }
   241      }
   242      opts.RecursiveDepth -= 1
   243      return pretouchRec(next, opts)
   244  }
   245  
   246  // Skip skips only one json value, and returns first non-blank character position and its ending position if it is valid.
   247  // Otherwise, returns negative error code using start and invalid character position using end
   248  func Skip(data []byte) (start int, end int) {
   249      s := rt.Mem2Str(data)
   250      p := 0
   251      m := types.NewStateMachine()
   252      ret := native.SkipOne(&s, &p, m, uint64(0))
   253      types.FreeStateMachine(m) 
   254      return ret, p
   255  }