github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/decoder/errors.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 `errors` 22 `fmt` 23 `reflect` 24 `strconv` 25 `strings` 26 27 `github.com/bytedance/sonic/internal/native/types` 28 `github.com/bytedance/sonic/internal/rt` 29 ) 30 31 type SyntaxError struct { 32 Pos int 33 Src string 34 Code types.ParsingError 35 Msg string 36 } 37 38 func (self SyntaxError) Error() string { 39 return fmt.Sprintf("%q", self.Description()) 40 } 41 42 func (self SyntaxError) Description() string { 43 return "Syntax error " + self.description() 44 } 45 46 func (self SyntaxError) description() string { 47 /* check for empty source */ 48 if self.Src == "" { 49 return fmt.Sprintf("no sources available: %#v", self) 50 } 51 52 p, x, q, y := calcBounds(len(self.Src), self.Pos) 53 54 /* compose the error description */ 55 return fmt.Sprintf( 56 "at index %d: %s\n\n\t%s\n\t%s^%s\n", 57 self.Pos, 58 self.Message(), 59 self.Src[p:q], 60 strings.Repeat(".", x), 61 strings.Repeat(".", y), 62 ) 63 } 64 65 func calcBounds(size int, pos int) (lbound int, lwidth int, rbound int, rwidth int) { 66 if pos >= size || pos < 0 { 67 return 0, 0, size, 0 68 } 69 70 i := 16 71 lbound = pos - i 72 rbound = pos + i 73 74 /* prevent slicing before the beginning */ 75 if lbound < 0 { 76 lbound, rbound, i = 0, rbound - lbound, i + lbound 77 } 78 79 /* prevent slicing beyond the end */ 80 if n := size; rbound > n { 81 n = rbound - n 82 rbound = size 83 84 /* move the left bound if possible */ 85 if lbound > n { 86 i += n 87 lbound -= n 88 } 89 } 90 91 /* left and right length */ 92 lwidth = clamp_zero(i) 93 rwidth = clamp_zero(rbound - lbound - i - 1) 94 95 return 96 } 97 98 func (self SyntaxError) Message() string { 99 if self.Msg == "" { 100 return self.Code.Message() 101 } 102 return self.Msg 103 } 104 105 func clamp_zero(v int) int { 106 if v < 0 { 107 return 0 108 } else { 109 return v 110 } 111 } 112 113 /** JIT Error Helpers **/ 114 115 var stackOverflow = &json.UnsupportedValueError { 116 Str : "Value nesting too deep", 117 Value : reflect.ValueOf("..."), 118 } 119 120 func error_wrap(src string, pos int, code types.ParsingError) error { 121 return *error_wrap_heap(src, pos, code) 122 } 123 124 //go:noinline 125 func error_wrap_heap(src string, pos int, code types.ParsingError) *SyntaxError { 126 return &SyntaxError { 127 Pos : pos, 128 Src : src, 129 Code : code, 130 } 131 } 132 133 func error_type(vt *rt.GoType) error { 134 return &json.UnmarshalTypeError{Type: vt.Pack()} 135 } 136 137 type MismatchTypeError struct { 138 Pos int 139 Src string 140 Type reflect.Type 141 } 142 143 func swithchJSONType (src string, pos int) string { 144 var val string 145 switch src[pos] { 146 case 'f': fallthrough 147 case 't': val = "bool" 148 case '"': val = "string" 149 case '{': val = "object" 150 case '[': val = "array" 151 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': val = "number" 152 } 153 return val 154 } 155 156 func (self MismatchTypeError) Error() string { 157 se := SyntaxError { 158 Pos : self.Pos, 159 Src : self.Src, 160 Code : types.ERR_MISMATCH, 161 } 162 return fmt.Sprintf("Mismatch type %s with value %s %q", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description()) 163 } 164 165 func (self MismatchTypeError) Description() string { 166 se := SyntaxError { 167 Pos : self.Pos, 168 Src : self.Src, 169 Code : types.ERR_MISMATCH, 170 } 171 return fmt.Sprintf("Mismatch type %s with value %s %s", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description()) 172 } 173 174 func error_mismatch(src string, pos int, vt *rt.GoType) error { 175 return &MismatchTypeError { 176 Pos : pos, 177 Src : src, 178 Type : vt.Pack(), 179 } 180 } 181 182 func error_field(name string) error { 183 return errors.New("json: unknown field " + strconv.Quote(name)) 184 } 185 186 func error_value(value string, vtype reflect.Type) error { 187 return &json.UnmarshalTypeError { 188 Type : vtype, 189 Value : value, 190 } 191 }