github.com/alloyzeus/go-azfl@v0.0.0-20231220071816-9740126a2d07/errors/descriptor.go (about) 1 package errors 2 3 // A ErrorDescriptor provides the description-part of an error. 4 // 5 // In a good practice, an error contains an information about *what* and *why*. 6 // A ErrorDescriptor abstracts the answers to the *why*. 7 // 8 // "User is not found" could be break down into "User" as the answer to the 9 // *what*, and "not found" as the answer to the *why*. Here, the ErrorDescriptor 10 // will contain the "not found". 11 // 12 // This interface could be used to describe any *what*, like the method 13 // in "method not implemented". For specific to data, see DataDescriptorError. 14 type ErrorDescriptor interface { 15 error 16 ErrorDescriptorString() string 17 } 18 19 type hasDescriptor interface { 20 Descriptor() ErrorDescriptor 21 } 22 23 func DescWrap(descriptor ErrorDescriptor, details error) error { 24 return descriptorDetailsError{descriptor: descriptor, details: details} 25 } 26 27 type descriptorDetailsError struct { 28 descriptor ErrorDescriptor 29 details error 30 } 31 32 var ( 33 _ error = descriptorDetailsError{} 34 _ hasDescriptor = descriptorDetailsError{} 35 _ Unwrappable = descriptorDetailsError{} 36 ) 37 38 func (e descriptorDetailsError) Error() string { 39 if e.descriptor != nil { 40 if e.details != nil { 41 return e.descriptor.Error() + ": " + e.details.Error() 42 } 43 return e.descriptor.Error() 44 } 45 if e.details != nil { 46 return e.details.Error() 47 } 48 return "" 49 } 50 51 func (e descriptorDetailsError) Descriptor() ErrorDescriptor { return e.descriptor } 52 func (e descriptorDetailsError) Unwrap() error { return e.details } 53 54 // constantErrorDescriptor is a generic error that designed to be declared 55 // as constant so that an instance could be easily compared by value to 56 // its original definiton. 57 // 58 // A constantErrorDescriptor is not providing a full context about an error, 59 // instead it's designed to be wrapped to provide context to the parent error. 60 type constantErrorDescriptor string 61 62 var ( 63 _ error = constantErrorDescriptor("") 64 _ ErrorDescriptor = constantErrorDescriptor("") 65 ) 66 67 func (e constantErrorDescriptor) Error() string { return string(e) } 68 func (e constantErrorDescriptor) ErrorDescriptorString() string { return string(e) } 69 70 func UnwrapDescriptor(err error) ErrorDescriptor { 71 if err != nil { 72 if d, ok := err.(hasDescriptor); ok { 73 return d.Descriptor() 74 } 75 } 76 return nil 77 } 78 79 func HasDescriptor(err error, desc ErrorDescriptor) bool { 80 d := UnwrapDescriptor(err) 81 //TODO: use other strategies. even reflect as the last resort 82 return d == desc 83 } 84 85 func HasDescriptorText(err error, descText string) bool { 86 d := UnwrapDescriptor(err) 87 return d.Error() == descText 88 } 89 90 func errorDescriptorString(err error) string { 91 if err != nil { 92 if desc, ok := err.(ErrorDescriptor); ok { 93 return desc.ErrorDescriptorString() 94 } 95 } 96 return "" 97 }