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 }