k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/internal/third_party/go-json-experiment/json/errors.go (about)

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package json
     6  
     7  import (
     8  	"errors"
     9  	"reflect"
    10  	"strconv"
    11  	"strings"
    12  	"unicode/utf8"
    13  )
    14  
    15  const errorPrefix = "json: "
    16  
    17  // Error matches errors returned by this package according to errors.Is.
    18  const Error = jsonError("json error")
    19  
    20  type jsonError string
    21  
    22  func (e jsonError) Error() string {
    23  	return string(e)
    24  }
    25  func (e jsonError) Is(target error) bool {
    26  	return e == target || target == Error
    27  }
    28  
    29  type ioError struct {
    30  	action string // either "read" or "write"
    31  	err    error
    32  }
    33  
    34  func (e *ioError) Error() string {
    35  	return errorPrefix + e.action + " error: " + e.err.Error()
    36  }
    37  func (e *ioError) Unwrap() error {
    38  	return e.err
    39  }
    40  func (e *ioError) Is(target error) bool {
    41  	return e == target || target == Error || errors.Is(e.err, target)
    42  }
    43  
    44  // SemanticError describes an error determining the meaning
    45  // of JSON data as Go data or vice-versa.
    46  //
    47  // The contents of this error as produced by this package may change over time.
    48  type SemanticError struct {
    49  	requireKeyedLiterals
    50  	nonComparable
    51  
    52  	action string // either "marshal" or "unmarshal"
    53  
    54  	// ByteOffset indicates that an error occurred after this byte offset.
    55  	ByteOffset int64
    56  	// JSONPointer indicates that an error occurred within this JSON value
    57  	// as indicated using the JSON Pointer notation (see RFC 6901).
    58  	JSONPointer string
    59  
    60  	// JSONKind is the JSON kind that could not be handled.
    61  	JSONKind Kind // may be zero if unknown
    62  	// GoType is the Go type that could not be handled.
    63  	GoType reflect.Type // may be nil if unknown
    64  
    65  	// Err is the underlying error.
    66  	Err error // may be nil
    67  }
    68  
    69  func (e *SemanticError) Error() string {
    70  	var sb strings.Builder
    71  	sb.WriteString(errorPrefix)
    72  
    73  	// Hyrum-proof the error message by deliberately switching between
    74  	// two equivalent renderings of the same error message.
    75  	// The randomization is tied to the Hyrum-proofing already applied
    76  	// on map iteration in Go.
    77  	for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} {
    78  		sb.WriteString(phrase)
    79  		break // use whichever phrase we get in the first iteration
    80  	}
    81  
    82  	// Format action.
    83  	var preposition string
    84  	switch e.action {
    85  	case "marshal":
    86  		sb.WriteString(" marshal")
    87  		preposition = " from"
    88  	case "unmarshal":
    89  		sb.WriteString(" unmarshal")
    90  		preposition = " into"
    91  	default:
    92  		sb.WriteString(" handle")
    93  		preposition = " with"
    94  	}
    95  
    96  	// Format JSON kind.
    97  	var omitPreposition bool
    98  	switch e.JSONKind {
    99  	case 'n':
   100  		sb.WriteString(" JSON null")
   101  	case 'f', 't':
   102  		sb.WriteString(" JSON boolean")
   103  	case '"':
   104  		sb.WriteString(" JSON string")
   105  	case '0':
   106  		sb.WriteString(" JSON number")
   107  	case '{', '}':
   108  		sb.WriteString(" JSON object")
   109  	case '[', ']':
   110  		sb.WriteString(" JSON array")
   111  	default:
   112  		omitPreposition = true
   113  	}
   114  
   115  	// Format Go type.
   116  	if e.GoType != nil {
   117  		if !omitPreposition {
   118  			sb.WriteString(preposition)
   119  		}
   120  		sb.WriteString(" Go value of type ")
   121  		sb.WriteString(e.GoType.String())
   122  	}
   123  
   124  	// Format where.
   125  	switch {
   126  	case e.JSONPointer != "":
   127  		sb.WriteString(" within JSON value at ")
   128  		sb.WriteString(strconv.Quote(e.JSONPointer))
   129  	case e.ByteOffset > 0:
   130  		sb.WriteString(" after byte offset ")
   131  		sb.WriteString(strconv.FormatInt(e.ByteOffset, 10))
   132  	}
   133  
   134  	// Format underlying error.
   135  	if e.Err != nil {
   136  		sb.WriteString(": ")
   137  		sb.WriteString(e.Err.Error())
   138  	}
   139  
   140  	return sb.String()
   141  }
   142  func (e *SemanticError) Is(target error) bool {
   143  	return e == target || target == Error || errors.Is(e.Err, target)
   144  }
   145  func (e *SemanticError) Unwrap() error {
   146  	return e.Err
   147  }
   148  
   149  // SyntacticError is a description of a syntactic error that occurred when
   150  // encoding or decoding JSON according to the grammar.
   151  //
   152  // The contents of this error as produced by this package may change over time.
   153  type SyntacticError struct {
   154  	requireKeyedLiterals
   155  	nonComparable
   156  
   157  	// ByteOffset indicates that an error occurred after this byte offset.
   158  	ByteOffset int64
   159  	str        string
   160  }
   161  
   162  func (e *SyntacticError) Error() string {
   163  	return errorPrefix + e.str
   164  }
   165  func (e *SyntacticError) Is(target error) bool {
   166  	return e == target || target == Error
   167  }
   168  func (e *SyntacticError) withOffset(pos int64) error {
   169  	return &SyntacticError{ByteOffset: pos, str: e.str}
   170  }
   171  
   172  func newInvalidCharacterError(prefix []byte, where string) *SyntacticError {
   173  	what := quoteRune(prefix)
   174  	return &SyntacticError{str: "invalid character " + what + " " + where}
   175  }
   176  
   177  func quoteRune(b []byte) string {
   178  	r, n := utf8.DecodeRune(b)
   179  	if r == utf8.RuneError && n == 1 {
   180  		return `'\x` + strconv.FormatUint(uint64(b[0]), 16) + `'`
   181  	}
   182  	return strconv.QuoteRune(r)
   183  }