forked from TrueCloudLab/rclone
Tardigrade Backend: Dependencies
This commit is contained in:
parent
962fbc8257
commit
03b629064a
544 changed files with 86690 additions and 2 deletions
648
vendor/github.com/spacemonkeygo/errors/errors.go
generated
vendored
Normal file
648
vendor/github.com/spacemonkeygo/errors/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,648 @@
|
|||
// Copyright (C) 2014 Space Monkey, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
logOnCreation = GenSym()
|
||||
captureStack = GenSym()
|
||||
disableInheritance = GenSym()
|
||||
)
|
||||
|
||||
// ErrorClass is the basic hierarchical error type. An ErrorClass generates
|
||||
// actual errors, but the error class controls properties of the errors it
|
||||
// generates, such as where those errors are in the hierarchy, whether or not
|
||||
// they capture the stack on instantiation, and so forth.
|
||||
type ErrorClass struct {
|
||||
parent *ErrorClass
|
||||
name string
|
||||
data map[DataKey]interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
// HierarchicalError is the base class for all hierarchical errors generated
|
||||
// through this class.
|
||||
HierarchicalError = &ErrorClass{
|
||||
parent: nil,
|
||||
name: "Error",
|
||||
data: map[DataKey]interface{}{captureStack: true}}
|
||||
|
||||
// SystemError is the base error class for errors not generated through this
|
||||
// errors library. It is not expected that anyone would ever generate new
|
||||
// errors from a SystemError type or make subclasses.
|
||||
SystemError = &ErrorClass{
|
||||
parent: nil,
|
||||
name: "System Error",
|
||||
data: map[DataKey]interface{}{}}
|
||||
)
|
||||
|
||||
// An ErrorOption is something that controls behavior of specific error
|
||||
// instances. They can be set on ErrorClasses or errors individually.
|
||||
type ErrorOption func(map[DataKey]interface{})
|
||||
|
||||
// SetData will take the given value and store it with the error or error class
|
||||
// and its descendents associated with the given DataKey. Be sure to check out
|
||||
// the example. value can be nil to disable values for subhierarchies.
|
||||
func SetData(key DataKey, value interface{}) ErrorOption {
|
||||
return func(m map[DataKey]interface{}) {
|
||||
m[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// LogOnCreation tells the error class and its descendents to log the stack
|
||||
// whenever an error of this class is created.
|
||||
func LogOnCreation() ErrorOption {
|
||||
return SetData(logOnCreation, true)
|
||||
}
|
||||
|
||||
// CaptureStack tells the error class and its descendents to capture the stack
|
||||
// whenever an error of this class is created, and output it as part of the
|
||||
// error's Error() method. This is the default.
|
||||
func CaptureStack() ErrorOption {
|
||||
return SetData(captureStack, true)
|
||||
}
|
||||
|
||||
// NoLogOnCreation is the opposite of LogOnCreation and applies to the error,
|
||||
// class, and its descendents. This is the default.
|
||||
func NoLogOnCreation() ErrorOption {
|
||||
return SetData(logOnCreation, false)
|
||||
}
|
||||
|
||||
// NoCaptureStack is the opposite of CaptureStack and applies to the error,
|
||||
// class, and its descendents.
|
||||
func NoCaptureStack() ErrorOption {
|
||||
return SetData(captureStack, false)
|
||||
}
|
||||
|
||||
// If DisableInheritance is provided, the error or error class will belong to
|
||||
// its ancestors, but will not inherit their settings and options. Use with
|
||||
// caution, and may disappear in future releases.
|
||||
func DisableInheritance() ErrorOption {
|
||||
return SetData(disableInheritance, true)
|
||||
}
|
||||
|
||||
func boolWrapper(val interface{}, default_value bool) bool {
|
||||
rv, ok := val.(bool)
|
||||
if ok {
|
||||
return rv
|
||||
}
|
||||
return default_value
|
||||
}
|
||||
|
||||
// NewClass creates an error class with the provided name and options. Classes
|
||||
// generated from this method and not *ErrorClass.NewClass will descend from
|
||||
// the root HierarchicalError base class.
|
||||
func NewClass(name string, options ...ErrorOption) *ErrorClass {
|
||||
return HierarchicalError.NewClass(name, options...)
|
||||
}
|
||||
|
||||
// New is for compatibility with the default Go errors package. It simply
|
||||
// creates an error from the HierarchicalError root class.
|
||||
func New(text string) error {
|
||||
// NewWith doesn't take a format string, even though we have no options.
|
||||
return HierarchicalError.NewWith(text)
|
||||
}
|
||||
|
||||
// NewClass creates an error class with the provided name and options. The new
|
||||
// class will descend from the receiver.
|
||||
func (parent *ErrorClass) NewClass(name string,
|
||||
options ...ErrorOption) *ErrorClass {
|
||||
|
||||
ec := &ErrorClass{
|
||||
parent: parent,
|
||||
name: name,
|
||||
data: make(map[DataKey]interface{})}
|
||||
|
||||
for _, option := range options {
|
||||
option(ec.data)
|
||||
}
|
||||
|
||||
if !boolWrapper(ec.data[disableInheritance], false) {
|
||||
// hoist options for speed
|
||||
for key, val := range parent.data {
|
||||
_, exists := ec.data[key]
|
||||
if !exists {
|
||||
ec.data[key] = val
|
||||
}
|
||||
}
|
||||
return ec
|
||||
} else {
|
||||
delete(ec.data, disableInheritance)
|
||||
}
|
||||
|
||||
return ec
|
||||
}
|
||||
|
||||
// MustAddData allows adding data key value pairs to error classes after they
|
||||
// are created. This is useful for allowing external packages add namespaced
|
||||
// values to errors defined outside of their package. It will panic if the
|
||||
// key is already set in the error class.
|
||||
func (e *ErrorClass) MustAddData(key DataKey, value interface{}) {
|
||||
if _, ex := e.data[key]; ex {
|
||||
panic("key already exists")
|
||||
}
|
||||
e.data[key] = value
|
||||
}
|
||||
|
||||
// GetData will return any data set on the error class for the given key. It
|
||||
// returns nil if there is no data set for that key.
|
||||
func (e *ErrorClass) GetData(key DataKey) interface{} {
|
||||
return e.data[key]
|
||||
}
|
||||
|
||||
// Parent returns this error class' direct ancestor.
|
||||
func (e *ErrorClass) Parent() *ErrorClass {
|
||||
return e.parent
|
||||
}
|
||||
|
||||
// String returns this error class' name
|
||||
func (e *ErrorClass) String() string {
|
||||
if e == nil {
|
||||
return "nil"
|
||||
}
|
||||
return e.name
|
||||
}
|
||||
|
||||
// Is returns true if the receiver class is or is a descendent of parent.
|
||||
func (e *ErrorClass) Is(parent *ErrorClass) bool {
|
||||
for check := e; check != nil; check = check.parent {
|
||||
if check == parent {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// frame logs the pc at some point during execution.
|
||||
type frame struct {
|
||||
pc uintptr
|
||||
}
|
||||
|
||||
// String returns a human readable form of the frame.
|
||||
func (e frame) String() string {
|
||||
if e.pc == 0 {
|
||||
return "unknown.unknown:0"
|
||||
}
|
||||
f := runtime.FuncForPC(e.pc)
|
||||
if f == nil {
|
||||
return "unknown.unknown:0"
|
||||
}
|
||||
file, line := f.FileLine(e.pc)
|
||||
return fmt.Sprintf("%s:%s:%d", f.Name(), filepath.Base(file), line)
|
||||
}
|
||||
|
||||
// callerState records the pc into an frame for two callers up.
|
||||
func callerState(depth int) frame {
|
||||
pc, _, _, ok := runtime.Caller(depth)
|
||||
if !ok {
|
||||
return frame{pc: 0}
|
||||
}
|
||||
return frame{pc: pc}
|
||||
}
|
||||
|
||||
// record will record the pc at the given depth into the error if it is
|
||||
// capable of recording it.
|
||||
func record(err error, depth int) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
cast.exits = append(cast.exits, callerState(depth))
|
||||
return cast
|
||||
}
|
||||
|
||||
// Record will record the current pc on the given error if possible, adding
|
||||
// to the error's recorded exits list. Returns the given error argument.
|
||||
func Record(err error) error {
|
||||
return record(err, 3)
|
||||
}
|
||||
|
||||
// RecordBefore will record the pc depth frames above the current stack frame
|
||||
// on the given error if possible, adding to the error's recorded exits list.
|
||||
// Record(err) is equivalent to RecordBefore(err, 0). Returns the given error
|
||||
// argument.
|
||||
func RecordBefore(err error, depth int) error {
|
||||
return record(err, 3+depth)
|
||||
}
|
||||
|
||||
// Error is the type that represents a specific error instance. It is not
|
||||
// expected that you will work with *Error classes directly. Instead, you
|
||||
// should use the 'error' interface and errors package methods that operate
|
||||
// on errors instances.
|
||||
type Error struct {
|
||||
err error
|
||||
class *ErrorClass
|
||||
stacks [][]frame
|
||||
exits []frame
|
||||
data map[DataKey]interface{}
|
||||
}
|
||||
|
||||
// GetData returns the value associated with the given DataKey on this error
|
||||
// or any of its ancestors. Please see the example for SetData
|
||||
func (e *Error) GetData(key DataKey) interface{} {
|
||||
if e.data != nil {
|
||||
val, ok := e.data[key]
|
||||
if ok {
|
||||
return val
|
||||
}
|
||||
if boolWrapper(e.data[disableInheritance], false) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return e.class.data[key]
|
||||
}
|
||||
|
||||
// GetData returns the value associated with the given DataKey on this error
|
||||
// or any of its ancestors. Please see the example for SetData
|
||||
func GetData(err error, key DataKey) interface{} {
|
||||
cast, ok := err.(*Error)
|
||||
if ok {
|
||||
return cast.GetData(key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ErrorClass) wrap(err error, classes []*ErrorClass,
|
||||
options []ErrorOption) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if ec, ok := err.(*Error); ok {
|
||||
if ec.Is(e) {
|
||||
if len(options) == 0 {
|
||||
return ec
|
||||
}
|
||||
// if we have options, we have to wrap it cause we don't want to
|
||||
// mutate the existing error.
|
||||
} else {
|
||||
for _, class := range classes {
|
||||
if ec.Is(class) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv := &Error{err: err, class: e}
|
||||
if len(options) > 0 {
|
||||
rv.data = make(map[DataKey]interface{})
|
||||
for _, option := range options {
|
||||
option(rv.data)
|
||||
}
|
||||
}
|
||||
|
||||
if boolWrapper(rv.GetData(captureStack), false) {
|
||||
rv.stacks = [][]frame{getStack(3)}
|
||||
}
|
||||
if boolWrapper(rv.GetData(logOnCreation), false) {
|
||||
LogWithStack(rv.Error())
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func getStack(depth int) (stack []frame) {
|
||||
var pcs [256]uintptr
|
||||
amount := runtime.Callers(depth+1, pcs[:])
|
||||
stack = make([]frame, amount)
|
||||
for i := 0; i < amount; i++ {
|
||||
stack[i] = frame{pcs[i]}
|
||||
}
|
||||
return stack
|
||||
}
|
||||
|
||||
// AttachStack adds another stack to the current error's stack trace if it
|
||||
// exists
|
||||
func AttachStack(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if len(cast.stacks) < 1 {
|
||||
// only record stacks if this error was supposed to
|
||||
return
|
||||
}
|
||||
cast.stacks = append(cast.stacks, getStack(2))
|
||||
}
|
||||
|
||||
// WrapUnless wraps the given error in the receiver error class unless the
|
||||
// error is already an instance of one of the provided error classes.
|
||||
func (e *ErrorClass) WrapUnless(err error, classes ...*ErrorClass) error {
|
||||
return e.wrap(err, classes, nil)
|
||||
}
|
||||
|
||||
// Wrap wraps the given error in the receiver error class with the provided
|
||||
// error-specific options.
|
||||
func (e *ErrorClass) Wrap(err error, options ...ErrorOption) error {
|
||||
return e.wrap(err, nil, options)
|
||||
}
|
||||
|
||||
// New makes a new error type. It takes a format string.
|
||||
func (e *ErrorClass) New(format string, args ...interface{}) error {
|
||||
return e.wrap(fmt.Errorf(format, args...), nil, nil)
|
||||
}
|
||||
|
||||
// NewWith makes a new error type with the provided error-specific options.
|
||||
func (e *ErrorClass) NewWith(message string, options ...ErrorOption) error {
|
||||
return e.wrap(errors.New(message), nil, options)
|
||||
}
|
||||
|
||||
// Error conforms to the error interface. Error will return the backtrace if
|
||||
// it was captured and any recorded exits.
|
||||
func (e *Error) Error() string {
|
||||
message := strings.TrimRight(e.err.Error(), "\n ")
|
||||
if strings.Contains(message, "\n") {
|
||||
message = fmt.Sprintf("%s:\n %s", e.class.String(),
|
||||
strings.Replace(message, "\n", "\n ", -1))
|
||||
} else {
|
||||
message = fmt.Sprintf("%s: %s", e.class.String(), message)
|
||||
}
|
||||
if stack := e.Stack(); stack != "" {
|
||||
message = fmt.Sprintf(
|
||||
"%s\n\"%s\" backtrace:\n%s", message, e.class, stack)
|
||||
}
|
||||
if exits := e.Exits(); exits != "" {
|
||||
message = fmt.Sprintf(
|
||||
"%s\n\"%s\" exits:\n%s", message, e.class, exits)
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
// Message returns just the error message without the backtrace or exits.
|
||||
func (e *Error) Message() string {
|
||||
message := strings.TrimRight(GetMessage(e.err), "\n ")
|
||||
if strings.Contains(message, "\n") {
|
||||
return fmt.Sprintf("%s:\n %s", e.class.String(),
|
||||
strings.Replace(message, "\n", "\n ", -1))
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", e.class.String(), message)
|
||||
}
|
||||
|
||||
// WrappedErr returns the wrapped error, if the current error is simply
|
||||
// wrapping some previously returned error or system error. You probably want
|
||||
// the package-level WrappedErr
|
||||
func (e *Error) WrappedErr() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
// WrappedErr returns the wrapped error, if the current error is simply
|
||||
// wrapping some previously returned error or system error. If the error isn't
|
||||
// hierarchical it is just returned.
|
||||
func WrappedErr(err error) error {
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
return cast.WrappedErr()
|
||||
}
|
||||
|
||||
// Class will return the appropriate error class for the given error. You
|
||||
// probably want the package-level GetClass.
|
||||
func (e *Error) Class() *ErrorClass {
|
||||
return e.class
|
||||
}
|
||||
|
||||
// Name returns the name of the error: in this case the name of the class the
|
||||
// error belongs to.
|
||||
func (e *Error) Name() (string, bool) {
|
||||
return e.class.name, true
|
||||
}
|
||||
|
||||
// GetClass will return the appropriate error class for the given error.
|
||||
// If the error is not nil, GetClass always returns a hierarchical error class,
|
||||
// and even attempts to determine a class for common system error types.
|
||||
func GetClass(err error) *ErrorClass {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return findSystemErrorClass(err)
|
||||
}
|
||||
return cast.class
|
||||
}
|
||||
|
||||
// Stack will return the stack associated with the error if one is found. You
|
||||
// probably want the package-level GetStack.
|
||||
func (e *Error) Stack() string {
|
||||
if len(e.stacks) > 0 {
|
||||
var frames []string
|
||||
for _, stack := range e.stacks {
|
||||
if frames == nil {
|
||||
frames = make([]string, 0, len(stack))
|
||||
} else {
|
||||
frames = append(frames, "----- attached stack -----")
|
||||
}
|
||||
for _, f := range stack {
|
||||
frames = append(frames, f.String())
|
||||
}
|
||||
}
|
||||
return strings.Join(frames, "\n")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetStack will return the stack associated with the error if one is found.
|
||||
func GetStack(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return cast.Stack()
|
||||
}
|
||||
|
||||
// Exits will return the exits recorded on the error if any are found. You
|
||||
// probably want the package-level GetExits.
|
||||
func (e *Error) Exits() string {
|
||||
if len(e.exits) > 0 {
|
||||
exits := make([]string, len(e.exits))
|
||||
for i, ex := range e.exits {
|
||||
exits[i] = ex.String()
|
||||
}
|
||||
return strings.Join(exits, "\n")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetExits will return the exits recorded on the error if any are found.
|
||||
func GetExits(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return cast.Exits()
|
||||
}
|
||||
|
||||
// GetMessage returns just the error message without the backtrace or exits.
|
||||
func GetMessage(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return err.Error()
|
||||
}
|
||||
return cast.Message()
|
||||
}
|
||||
|
||||
// EquivalenceOption values control behavior of determining whether or not an
|
||||
// error belongs to a specific class.
|
||||
type EquivalenceOption int
|
||||
|
||||
const (
|
||||
// If IncludeWrapped is used, wrapped errors are also used for determining
|
||||
// class membership.
|
||||
IncludeWrapped EquivalenceOption = 1
|
||||
)
|
||||
|
||||
func combineEquivOpts(opts []EquivalenceOption) (rv EquivalenceOption) {
|
||||
for _, opt := range opts {
|
||||
rv |= opt
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// Is returns whether or not an error belongs to a specific class. Typically
|
||||
// you should use Contains instead.
|
||||
func (e *Error) Is(ec *ErrorClass, opts ...EquivalenceOption) bool {
|
||||
return ec.Contains(e, opts...)
|
||||
}
|
||||
|
||||
// Contains returns whether or not the receiver error class contains the given
|
||||
// error instance.
|
||||
func (e *ErrorClass) Contains(err error, opts ...EquivalenceOption) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
cast, ok := err.(*Error)
|
||||
if !ok {
|
||||
return findSystemErrorClass(err).Is(e)
|
||||
}
|
||||
if cast.class.Is(e) {
|
||||
return true
|
||||
}
|
||||
if combineEquivOpts(opts)&IncludeWrapped == 0 {
|
||||
return false
|
||||
}
|
||||
return e.Contains(cast.err, opts...)
|
||||
}
|
||||
|
||||
var (
|
||||
// Useful error classes
|
||||
NotImplementedError = NewClass("Not Implemented Error", LogOnCreation())
|
||||
ProgrammerError = NewClass("Programmer Error", LogOnCreation())
|
||||
PanicError = NewClass("Panic Error", LogOnCreation())
|
||||
|
||||
// The following SystemError descendants are provided such that the GetClass
|
||||
// method has something to return for standard library error types not
|
||||
// defined through this class.
|
||||
//
|
||||
// It is not expected that anyone would create instances of these classes.
|
||||
//
|
||||
// from os
|
||||
SyscallError = SystemError.NewClass("Syscall Error")
|
||||
// from syscall
|
||||
ErrnoError = SystemError.NewClass("Errno Error")
|
||||
// from net
|
||||
NetworkError = SystemError.NewClass("Network Error")
|
||||
UnknownNetworkError = NetworkError.NewClass("Unknown Network Error")
|
||||
AddrError = NetworkError.NewClass("Addr Error")
|
||||
InvalidAddrError = AddrError.NewClass("Invalid Addr Error")
|
||||
NetOpError = NetworkError.NewClass("Network Op Error")
|
||||
NetParseError = NetworkError.NewClass("Network Parse Error")
|
||||
DNSError = NetworkError.NewClass("DNS Error")
|
||||
DNSConfigError = DNSError.NewClass("DNS Config Error")
|
||||
// from io
|
||||
IOError = SystemError.NewClass("IO Error")
|
||||
EOF = IOError.NewClass("EOF")
|
||||
ClosedPipeError = IOError.NewClass("Closed Pipe Error")
|
||||
NoProgressError = IOError.NewClass("No Progress Error")
|
||||
ShortBufferError = IOError.NewClass("Short Buffer Error")
|
||||
ShortWriteError = IOError.NewClass("Short Write Error")
|
||||
UnexpectedEOFError = IOError.NewClass("Unexpected EOF Error")
|
||||
// from context
|
||||
ContextError = SystemError.NewClass("Context Error")
|
||||
ContextCanceled = ContextError.NewClass("Canceled")
|
||||
ContextTimeout = ContextError.NewClass("Timeout")
|
||||
)
|
||||
|
||||
func findSystemErrorClass(err error) *ErrorClass {
|
||||
switch err {
|
||||
case io.EOF:
|
||||
return EOF
|
||||
case io.ErrUnexpectedEOF:
|
||||
return UnexpectedEOFError
|
||||
case io.ErrClosedPipe:
|
||||
return ClosedPipeError
|
||||
case io.ErrNoProgress:
|
||||
return NoProgressError
|
||||
case io.ErrShortBuffer:
|
||||
return ShortBufferError
|
||||
case io.ErrShortWrite:
|
||||
return ShortWriteError
|
||||
case contextCanceled:
|
||||
return ContextCanceled
|
||||
case contextDeadlineExceeded:
|
||||
return ContextTimeout
|
||||
default:
|
||||
break
|
||||
}
|
||||
if isErrnoError(err) {
|
||||
return ErrnoError
|
||||
}
|
||||
switch err.(type) {
|
||||
case *os.SyscallError:
|
||||
return SyscallError
|
||||
case net.UnknownNetworkError:
|
||||
return UnknownNetworkError
|
||||
case *net.AddrError:
|
||||
return AddrError
|
||||
case net.InvalidAddrError:
|
||||
return InvalidAddrError
|
||||
case *net.OpError:
|
||||
return NetOpError
|
||||
case *net.ParseError:
|
||||
return NetParseError
|
||||
case *net.DNSError:
|
||||
return DNSError
|
||||
case *net.DNSConfigError:
|
||||
return DNSConfigError
|
||||
case net.Error:
|
||||
return NetworkError
|
||||
default:
|
||||
return SystemError
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue