mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-09-27 14:10:24 +00:00
121 lines
3.6 KiB
Go
121 lines
3.6 KiB
Go
|
// Copyright 2016, Joe Tsai. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE.md file.
|
||
|
|
||
|
// Package errors implements functions to manipulate compression errors.
|
||
|
//
|
||
|
// In idiomatic Go, it is an anti-pattern to use panics as a form of error
|
||
|
// reporting in the API. Instead, the expected way to transmit errors is by
|
||
|
// returning an error value. Unfortunately, the checking of "err != nil" in
|
||
|
// tight loops commonly found in compression causes non-negligible performance
|
||
|
// degradation. While this may not be idiomatic, the internal packages of this
|
||
|
// repository rely on panics as a normal means to convey errors. In order to
|
||
|
// ensure that these panics do not leak across the public API, the public
|
||
|
// packages must recover from these panics and present an error value.
|
||
|
//
|
||
|
// The Panic and Recover functions in this package provide a safe way to
|
||
|
// recover from errors only generated from within this repository.
|
||
|
//
|
||
|
// Example usage:
|
||
|
// func Foo() (err error) {
|
||
|
// defer errors.Recover(&err)
|
||
|
//
|
||
|
// if rand.Intn(2) == 0 {
|
||
|
// // Unexpected panics will not be caught by Recover.
|
||
|
// io.Closer(nil).Close()
|
||
|
// } else {
|
||
|
// // Errors thrown by Panic will be caught by Recover.
|
||
|
// errors.Panic(errors.New("whoopsie"))
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
package errors
|
||
|
|
||
|
import "strings"
|
||
|
|
||
|
const (
|
||
|
// Unknown indicates that there is no classification for this error.
|
||
|
Unknown = iota
|
||
|
|
||
|
// Internal indicates that this error is due to an internal bug.
|
||
|
// Users should file a issue report if this type of error is encountered.
|
||
|
Internal
|
||
|
|
||
|
// Invalid indicates that this error is due to the user misusing the API
|
||
|
// and is indicative of a bug on the user's part.
|
||
|
Invalid
|
||
|
|
||
|
// Deprecated indicates the use of a deprecated and unsupported feature.
|
||
|
Deprecated
|
||
|
|
||
|
// Corrupted indicates that the input stream is corrupted.
|
||
|
Corrupted
|
||
|
|
||
|
// Closed indicates that the handlers are closed.
|
||
|
Closed
|
||
|
)
|
||
|
|
||
|
var codeMap = map[int]string{
|
||
|
Unknown: "unknown error",
|
||
|
Internal: "internal error",
|
||
|
Invalid: "invalid argument",
|
||
|
Deprecated: "deprecated format",
|
||
|
Corrupted: "corrupted input",
|
||
|
Closed: "closed handler",
|
||
|
}
|
||
|
|
||
|
type Error struct {
|
||
|
Code int // The error type
|
||
|
Pkg string // Name of the package where the error originated
|
||
|
Msg string // Descriptive message about the error (optional)
|
||
|
}
|
||
|
|
||
|
func (e Error) Error() string {
|
||
|
var ss []string
|
||
|
for _, s := range []string{e.Pkg, codeMap[e.Code], e.Msg} {
|
||
|
if s != "" {
|
||
|
ss = append(ss, s)
|
||
|
}
|
||
|
}
|
||
|
return strings.Join(ss, ": ")
|
||
|
}
|
||
|
|
||
|
func (e Error) CompressError() {}
|
||
|
func (e Error) IsInternal() bool { return e.Code == Internal }
|
||
|
func (e Error) IsInvalid() bool { return e.Code == Invalid }
|
||
|
func (e Error) IsDeprecated() bool { return e.Code == Deprecated }
|
||
|
func (e Error) IsCorrupted() bool { return e.Code == Corrupted }
|
||
|
func (e Error) IsClosed() bool { return e.Code == Closed }
|
||
|
|
||
|
func IsInternal(err error) bool { return isCode(err, Internal) }
|
||
|
func IsInvalid(err error) bool { return isCode(err, Invalid) }
|
||
|
func IsDeprecated(err error) bool { return isCode(err, Deprecated) }
|
||
|
func IsCorrupted(err error) bool { return isCode(err, Corrupted) }
|
||
|
func IsClosed(err error) bool { return isCode(err, Closed) }
|
||
|
|
||
|
func isCode(err error, code int) bool {
|
||
|
if cerr, ok := err.(Error); ok && cerr.Code == code {
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// errWrap is used by Panic and Recover to ensure that only errors raised by
|
||
|
// Panic are recovered by Recover.
|
||
|
type errWrap struct{ e *error }
|
||
|
|
||
|
func Recover(err *error) {
|
||
|
switch ex := recover().(type) {
|
||
|
case nil:
|
||
|
// Do nothing.
|
||
|
case errWrap:
|
||
|
*err = *ex.e
|
||
|
default:
|
||
|
panic(ex)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Panic(err error) {
|
||
|
panic(errWrap{&err})
|
||
|
}
|