...

Source file src/errors/wrap.go

     1	// Copyright 2018 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 errors
     6	
     7	import (
     8		"internal/reflectlite"
     9	)
    10	
    11	// Unwrap returns the result of calling the Unwrap method on err, if err's
    12	// type contains an Unwrap method returning error.
    13	// Otherwise, Unwrap returns nil.
    14	func Unwrap(err error) error {
    15		u, ok := err.(interface {
    16			Unwrap() error
    17		})
    18		if !ok {
    19			return nil
    20		}
    21		return u.Unwrap()
    22	}
    23	
    24	// Is reports whether any error in err's chain matches target.
    25	//
    26	// The chain consists of err itself followed by the sequence of errors obtained by
    27	// repeatedly calling Unwrap.
    28	//
    29	// An error is considered to match a target if it is equal to that target or if
    30	// it implements a method Is(error) bool such that Is(target) returns true.
    31	func Is(err, target error) bool {
    32		if target == nil {
    33			return err == target
    34		}
    35	
    36		isComparable := reflectlite.TypeOf(target).Comparable()
    37		for {
    38			if isComparable && err == target {
    39				return true
    40			}
    41			if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
    42				return true
    43			}
    44			// TODO: consider supporing target.Is(err). This would allow
    45			// user-definable predicates, but also may allow for coping with sloppy
    46			// APIs, thereby making it easier to get away with them.
    47			if err = Unwrap(err); err == nil {
    48				return false
    49			}
    50		}
    51	}
    52	
    53	// As finds the first error in err's chain that matches target, and if so, sets
    54	// target to that error value and returns true.
    55	//
    56	// The chain consists of err itself followed by the sequence of errors obtained by
    57	// repeatedly calling Unwrap.
    58	//
    59	// An error matches target if the error's concrete value is assignable to the value
    60	// pointed to by target, or if the error has a method As(interface{}) bool such that
    61	// As(target) returns true. In the latter case, the As method is responsible for
    62	// setting target.
    63	//
    64	// As will panic if target is not a non-nil pointer to either a type that implements
    65	// error, or to any interface type. As returns false if err is nil.
    66	func As(err error, target interface{}) bool {
    67		if target == nil {
    68			panic("errors: target cannot be nil")
    69		}
    70		val := reflectlite.ValueOf(target)
    71		typ := val.Type()
    72		if typ.Kind() != reflectlite.Ptr || val.IsNil() {
    73			panic("errors: target must be a non-nil pointer")
    74		}
    75		if e := typ.Elem(); e.Kind() != reflectlite.Interface && !e.Implements(errorType) {
    76			panic("errors: *target must be interface or implement error")
    77		}
    78		targetType := typ.Elem()
    79		for err != nil {
    80			if reflectlite.TypeOf(err).AssignableTo(targetType) {
    81				val.Elem().Set(reflectlite.ValueOf(err))
    82				return true
    83			}
    84			if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
    85				return true
    86			}
    87			err = Unwrap(err)
    88		}
    89		return false
    90	}
    91	
    92	var errorType = reflectlite.TypeOf((*error)(nil)).Elem()
    93	

View as plain text