// Copyright (C) 2022-2023 Luke Shumaker // // SPDX-License-Identifier: GPL-2.0-or-later package lowmemjson import ( "encoding/json" "errors" "fmt" "reflect" "strings" "git.lukeshu.com/go/lowmemjson/internal/jsonparse" ) // ErrInvalidUnreadRune is returned to Decodable.DecodeJSON(scanner) // implementations from scanner.UnreadRune() if the last operation was // not a successful .ReadRune() call. var ErrInvalidUnreadRune = errors.New("lowmemjson: invalid use of UnreadRune") // parser errors /////////////////////////////////////////////////////////////////////////////////// // ErrParserExceededMaxDepth is the base error that a // *DecodeSyntaxError wraps when the depth of the JSON document // exceeds 10000. var ErrParserExceededMaxDepth = jsonparse.ErrParserExceededMaxDepth // low-level decode errors ///////////////////////////////////////////////////////////////////////// // These will be wrapped in a *DecodeError. // A DecodeReadError is returned from Decode (wrapped in a // *DecodeError) if there is an I/O error reading the input. type DecodeReadError struct { Err error Offset int64 } func (e *DecodeReadError) Error() string { return fmt.Sprintf("json: I/O error at input byte %v: %v", e.Offset, e.Err) } func (e *DecodeReadError) Unwrap() error { return e.Err } // A DecodeSyntaxError is returned from Decode (wrapped in a // *DecodeError) if there is a syntax error in the input. type DecodeSyntaxError struct { Err error Offset int64 } func (e *DecodeSyntaxError) Error() string { return fmt.Sprintf("json: syntax error at input byte %v: %v", e.Offset, e.Err) } func (e *DecodeSyntaxError) Unwrap() error { return e.Err } // A DecodeTypeError is returned from Decode (wrapped in a // *DecodeError) if the JSON input is not appropriate for the given Go // type. // // If a .DecodeJSON, .UnmarshalJSON, or .UnmashaleText method returns // an error, it is wrapped in a *DecodeTypeError. type DecodeTypeError struct { JSONType string // (optional) GoType reflect.Type Offset int64 Err error // (optional) } func (e *DecodeTypeError) Error() string { var buf strings.Builder buf.WriteString("json: cannot decode ") if e.JSONType != "" { fmt.Fprintf(&buf, "JSON %s ", e.JSONType) } fmt.Fprintf(&buf, "at input byte %v into Go %v", e.Offset, e.GoType) if e.Err != nil { fmt.Fprintf(&buf, ": %v", strings.TrimPrefix(e.Err.Error(), "json: ")) } return buf.String() } func (e *DecodeTypeError) Unwrap() error { return e.Err } // ErrDecodeNonEmptyInterface is the base error that a // *DecodeTypeError wraps when Decode is asked to unmarshal into an // `interface` type that has one or more methods. var ErrDecodeNonEmptyInterface = errors.New("cannot decode into non-empty interface") // high-level decode errors //////////////////////////////////////////////////////////////////////// // A DecodeArgumentError is returned from Decode if the argument is // not a non-nil pointer or is not settable. // // Alternatively, a *DecodeArgument error may be found inside of a // *DecodeTypeError if the type being decoded into is not a type that // can be decoded into (such as map with non-stringable type as keys). // // type DecodeArgumentError struct { // Type reflect.Type // } type DecodeArgumentError = json.InvalidUnmarshalError // A DecodeError is returned from Decode for all errors except for // *DecodeArgumentError. // // A *DecodeError wraps *DecodeSyntaxError for malformed or illegal // input, *DecodeTypeError for Go type issues, or *DecodeReadError for // I/O errors. type DecodeError struct { Field string // Where in the JSON the error was, in the form "v[idx][idx][idx]". Err error // What the error was. FieldParent string // for compat; the same as encoding/json.UnmarshalTypeError.Struct FieldName string // for compat; the same as encoding/json.UnmarshalTypeError.Field } func (e *DecodeError) Error() string { return fmt.Sprintf("json: %s: %s", e.Field, strings.TrimPrefix(e.Err.Error(), "json: ")) } func (e *DecodeError) Unwrap() error { return e.Err } // encode errors /////////////////////////////////////////////////////////////////////////////////// // A EncodeWriteError is returned from Encode if there is an error // writing to the output stream. type EncodeWriteError struct { Err error Offset int64 } func (e *EncodeWriteError) Error() string { return fmt.Sprintf("json: I/O error at output byte %v: %v", e.Offset, e.Err) } func (e *EncodeWriteError) Unwrap() error { return e.Err } // An EncodeTypeError is returned by Encode when attempting to encode // an unsupported type. // // type EncodeTypeError struct { // Type reflect.Type // } type EncodeTypeError = json.UnsupportedTypeError // An EncodeValueError is returned by Encode when attempting to encode // an unsupported value (such as a datastructure with a cycle, or (if // InvalidUTF8=InvalidUTF8Error) a string with invalid UTF-8). // // type UnsupportedValueError struct { // Value reflect.Value // Str string // } type EncodeValueError = json.UnsupportedValueError // An EncodeMethodError either wraps an error that is returned from an // object's method when encoding that object to JSON, or wraps a // *ReEncodeSyntaxError for the method's output. type EncodeMethodError struct { Type reflect.Type // The Go type that the method is on SourceFunc string // The method: "EncodeJSON", "MarshalJSON", or "MarshalText" Err error // The error that the method returned } func (e *EncodeMethodError) Error() string { return fmt.Sprintf("json: error calling %v for type %v: %v", e.SourceFunc, e.Type, strings.TrimPrefix(e.Err.Error(), "json: ")) } func (e *EncodeMethodError) Unwrap() error { return e.Err } // reencode errors ///////////////////////////////////////////////////////////////////////////////// // A ReEncodeWriteError is returned from ReEncoder's methods if there // is an error writing to the output stream. type ReEncodeWriteError struct { Err error Offset int64 } func (e *ReEncodeWriteError) Error() string { return fmt.Sprintf("json: I/O error at output byte %v: %v", e.Offset, e.Err) } func (e *ReEncodeWriteError) Unwrap() error { return e.Err } // A ReEncodeSyntaxError is returned from ReEncoder's methods if there // is a syntax error in the input. type ReEncodeSyntaxError struct { Err error Offset int64 } func (e *ReEncodeSyntaxError) Error() string { return fmt.Sprintf("json: syntax error at input byte %v: %v", e.Offset, e.Err) } func (e *ReEncodeSyntaxError) Unwrap() error { return e.Err }