podman
175 строк · 3.9 Кб
1// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
2// Use of this source code is governed by a MIT style
3// license that can be found in the LICENSE file.
4
5package gin6
7import (8"fmt"9"reflect"10"strings"11
12"github.com/gin-gonic/gin/internal/json"13)
14
15// ErrorType is an unsigned 64-bit error code as defined in the gin spec.
16type ErrorType uint6417
18const (19// ErrorTypeBind is used when Context.Bind() fails.20ErrorTypeBind ErrorType = 1 << 6321// ErrorTypeRender is used when Context.Render() fails.22ErrorTypeRender ErrorType = 1 << 6223// ErrorTypePrivate indicates a private error.24ErrorTypePrivate ErrorType = 1 << 025// ErrorTypePublic indicates a public error.26ErrorTypePublic ErrorType = 1 << 127// ErrorTypeAny indicates any other error.28ErrorTypeAny ErrorType = 1<<64 - 129// ErrorTypeNu indicates any other error.30ErrorTypeNu = 231)
32
33// Error represents a error's specification.
34type Error struct {35Err error36Type ErrorType
37Meta any
38}
39
40type errorMsgs []*Error41
42var _ error = (*Error)(nil)43
44// SetType sets the error's type.
45func (msg *Error) SetType(flags ErrorType) *Error {46msg.Type = flags47return msg48}
49
50// SetMeta sets the error's meta data.
51func (msg *Error) SetMeta(data any) *Error {52msg.Meta = data53return msg54}
55
56// JSON creates a properly formatted JSON
57func (msg *Error) JSON() any {58jsonData := H{}59if msg.Meta != nil {60value := reflect.ValueOf(msg.Meta)61switch value.Kind() {62case reflect.Struct:63return msg.Meta64case reflect.Map:65for _, key := range value.MapKeys() {66jsonData[key.String()] = value.MapIndex(key).Interface()67}68default:69jsonData["meta"] = msg.Meta70}71}72if _, ok := jsonData["error"]; !ok {73jsonData["error"] = msg.Error()74}75return jsonData76}
77
78// MarshalJSON implements the json.Marshaller interface.
79func (msg *Error) MarshalJSON() ([]byte, error) {80return json.Marshal(msg.JSON())81}
82
83// Error implements the error interface.
84func (msg Error) Error() string {85return msg.Err.Error()86}
87
88// IsType judges one error.
89func (msg *Error) IsType(flags ErrorType) bool {90return (msg.Type & flags) > 091}
92
93// Unwrap returns the wrapped error, to allow interoperability with errors.Is(), errors.As() and errors.Unwrap()
94func (msg *Error) Unwrap() error {95return msg.Err96}
97
98// ByType returns a readonly copy filtered the byte.
99// ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic.
100func (a errorMsgs) ByType(typ ErrorType) errorMsgs {101if len(a) == 0 {102return nil103}104if typ == ErrorTypeAny {105return a106}107var result errorMsgs108for _, msg := range a {109if msg.IsType(typ) {110result = append(result, msg)111}112}113return result114}
115
116// Last returns the last error in the slice. It returns nil if the array is empty.
117// Shortcut for errors[len(errors)-1].
118func (a errorMsgs) Last() *Error {119if length := len(a); length > 0 {120return a[length-1]121}122return nil123}
124
125// Errors returns an array with all the error messages.
126// Example:
127//
128// c.Error(errors.New("first"))
129// c.Error(errors.New("second"))
130// c.Error(errors.New("third"))
131// c.Errors.Errors() // == []string{"first", "second", "third"}
132func (a errorMsgs) Errors() []string {133if len(a) == 0 {134return nil135}136errorStrings := make([]string, len(a))137for i, err := range a {138errorStrings[i] = err.Error()139}140return errorStrings141}
142
143func (a errorMsgs) JSON() any {144switch length := len(a); length {145case 0:146return nil147case 1:148return a.Last().JSON()149default:150jsonData := make([]any, length)151for i, err := range a {152jsonData[i] = err.JSON()153}154return jsonData155}156}
157
158// MarshalJSON implements the json.Marshaller interface.
159func (a errorMsgs) MarshalJSON() ([]byte, error) {160return json.Marshal(a.JSON())161}
162
163func (a errorMsgs) String() string {164if len(a) == 0 {165return ""166}167var buffer strings.Builder168for i, msg := range a {169fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err)170if msg.Meta != nil {171fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)172}173}174return buffer.String()175}
176