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 }