123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- /*
- * Copyright 2021 ByteDance Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package decoder
- import (
- `encoding/json`
- `errors`
- `fmt`
- `reflect`
- `strconv`
- `strings`
- `github.com/bytedance/sonic/internal/native/types`
- `github.com/bytedance/sonic/internal/rt`
- )
- type SyntaxError struct {
- Pos int
- Src string
- Code types.ParsingError
- Msg string
- }
- func (self SyntaxError) Error() string {
- return fmt.Sprintf("%q", self.Description())
- }
- func (self SyntaxError) Description() string {
- return "Syntax error " + self.description()
- }
- func (self SyntaxError) description() string {
- /* check for empty source */
- if self.Src == "" {
- return fmt.Sprintf("no sources available: %#v", self)
- }
- p, x, q, y := calcBounds(len(self.Src), self.Pos)
- /* compose the error description */
- return fmt.Sprintf(
- "at index %d: %s\n\n\t%s\n\t%s^%s\n",
- self.Pos,
- self.Message(),
- self.Src[p:q],
- strings.Repeat(".", x),
- strings.Repeat(".", y),
- )
- }
- func calcBounds(size int, pos int) (lbound int, lwidth int, rbound int, rwidth int) {
- if pos >= size || pos < 0 {
- return 0, 0, size, 0
- }
- i := 16
- lbound = pos - i
- rbound = pos + i
- /* prevent slicing before the beginning */
- if lbound < 0 {
- lbound, rbound, i = 0, rbound - lbound, i + lbound
- }
- /* prevent slicing beyond the end */
- if n := size; rbound > n {
- n = rbound - n
- rbound = size
- /* move the left bound if possible */
- if lbound > n {
- i += n
- lbound -= n
- }
- }
- /* left and right length */
- lwidth = clamp_zero(i)
- rwidth = clamp_zero(rbound - lbound - i - 1)
- return
- }
- func (self SyntaxError) Message() string {
- if self.Msg == "" {
- return self.Code.Message()
- }
- return self.Msg
- }
- func clamp_zero(v int) int {
- if v < 0 {
- return 0
- } else {
- return v
- }
- }
- /** JIT Error Helpers **/
- var stackOverflow = &json.UnsupportedValueError {
- Str : "Value nesting too deep",
- Value : reflect.ValueOf("..."),
- }
- func error_wrap(src string, pos int, code types.ParsingError) error {
- return *error_wrap_heap(src, pos, code)
- }
- //go:noinline
- func error_wrap_heap(src string, pos int, code types.ParsingError) *SyntaxError {
- return &SyntaxError {
- Pos : pos,
- Src : src,
- Code : code,
- }
- }
- func error_type(vt *rt.GoType) error {
- return &json.UnmarshalTypeError{Type: vt.Pack()}
- }
- type MismatchTypeError struct {
- Pos int
- Src string
- Type reflect.Type
- }
- func swithchJSONType (src string, pos int) string {
- var val string
- switch src[pos] {
- case 'f': fallthrough
- case 't': val = "bool"
- case '"': val = "string"
- case '{': val = "object"
- case '[': val = "array"
- case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': val = "number"
- }
- return val
- }
- func (self MismatchTypeError) Error() string {
- se := SyntaxError {
- Pos : self.Pos,
- Src : self.Src,
- Code : types.ERR_MISMATCH,
- }
- return fmt.Sprintf("Mismatch type %s with value %s %q", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description())
- }
- func (self MismatchTypeError) Description() string {
- se := SyntaxError {
- Pos : self.Pos,
- Src : self.Src,
- Code : types.ERR_MISMATCH,
- }
- return fmt.Sprintf("Mismatch type %s with value %s %s", self.Type.String(), swithchJSONType(self.Src, self.Pos), se.description())
- }
- func error_mismatch(src string, pos int, vt *rt.GoType) error {
- return &MismatchTypeError {
- Pos : pos,
- Src : src,
- Type : vt.Pack(),
- }
- }
- func error_field(name string) error {
- return errors.New("json: unknown field " + strconv.Quote(name))
- }
- func error_value(value string, vtype reflect.Type) error {
- return &json.UnmarshalTypeError {
- Type : vtype,
- Value : value,
- }
- }
|