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 }