github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/proto/generic/error.go (about) 1 /** 2 * Copyright 2023 CloudWeGo Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package generic 18 19 import ( 20 "fmt" 21 "unsafe" 22 23 "github.com/cloudwego/dynamicgo/meta" 24 "github.com/cloudwego/dynamicgo/proto" 25 ) 26 27 var ( 28 errNotFound = errNode(meta.ErrNotFound, "", nil) 29 ) 30 31 //go:noinline 32 func wrapError(code meta.ErrCode, msg string, err error) error { 33 return meta.NewError(meta.NewErrorCode(code, meta.PROTOBUF), msg, err) 34 } 35 36 //go:noinline 37 func unwrapError(msg string, err error) error { 38 if v, ok := err.(meta.Error); ok { 39 return wrapError(v.Code, msg, err) 40 } else if v, ok := err.(Value); ok { 41 return wrapError(v.ErrCode(), msg, err) 42 } else if v, ok := err.(Node); ok { 43 return wrapError(v.ErrCode(), msg, err) 44 } else { 45 return wrapError(0, msg, err) 46 } 47 } 48 49 //go:noinline 50 func wrapValue(n Node, desc *proto.TypeDescriptor) Value { 51 return Value{ 52 Node: n, 53 Desc: desc, 54 } 55 } 56 57 //go:noinline 58 func errNode(code meta.ErrCode, msg string, err error) Node { 59 // panic(code.Behavior()) 60 e := meta.NewError(meta.NewErrorCode(code, meta.PROTOBUF), msg, err).(meta.Error) 61 return Node{ 62 t: proto.ERROR, 63 l: int(code), 64 v: unsafe.Pointer(&e), 65 } 66 } 67 68 const ( 69 lastErrNotFoud proto.Type = 0 // UNKNOWN Type 70 ) 71 72 //go:noinline 73 func errNotFoundLast(ptr unsafe.Pointer, parent proto.Type) Node { 74 return Node{ 75 t: proto.ERROR, 76 et: lastErrNotFoud, 77 kt: parent, 78 l: int(meta.ErrNotFound), 79 v: ptr, 80 } 81 } 82 83 //go:noinline 84 func errValue(code meta.ErrCode, msg string, err error) Value { 85 e := meta.NewError(meta.NewErrorCode(code, meta.PROTOBUF), msg, err).(meta.Error) 86 return Value{ 87 Node: Node{ 88 t: proto.ERROR, 89 l: int(code), 90 v: unsafe.Pointer(&e), 91 }, 92 } 93 } 94 95 //go:noinline 96 func errPathNode(code meta.ErrCode, msg string, err error) *PathNode { 97 // panic(code.Behavior()) 98 e := meta.NewError(meta.NewErrorCode(code, meta.PROTOBUF), msg, err).(meta.Error) 99 return &PathNode{ 100 Node: Node{ 101 t: proto.ERROR, 102 l: int(code), 103 v: unsafe.Pointer(&e), 104 }, 105 } 106 } 107 108 // IsEmpty tells if the node is proto.UNKNOWN 109 func (self Node) IsUnKnown() bool { 110 return self.t == proto.UNKNOWN 111 } 112 113 // IsEmtpy tells if the node is PROTOBUF.ERROR 114 func (self Node) IsError() bool { 115 return self.t == proto.ERROR 116 } 117 118 // IsErrorNotFound tells if the node is not-found-data error 119 func (self Node) IsErrNotFound() bool { 120 return self.t == proto.ERROR && self.l == int(meta.ErrNotFound) 121 } 122 123 func (self Node) isErrNotFoundLast() bool { 124 return self.IsErrNotFound() && self.et == lastErrNotFoud 125 } 126 127 // ErrCode return the meta.ErrCode of a ERROR node 128 func (self Node) ErrCode() meta.ErrCode { 129 if self.t != proto.ERROR { 130 return 0 131 } 132 return meta.ErrCode(self.l) 133 } 134 135 // Check checks if it is a ERROR node and returns corresponding error 136 func (self *Node) Check() error { 137 if self == nil { 138 return fmt.Errorf("nil node") 139 } 140 if err := self.Error(); err != "" { 141 return self 142 } 143 return nil 144 } 145 146 // Error return error message if it is a ERROR node 147 func (self Node) Error() string { 148 switch self.t { 149 case proto.ERROR: 150 if self.v != nil && self.et != lastErrNotFoud { 151 return (*meta.Error)(self.v).Error() 152 } 153 return fmt.Sprintf("%s", meta.ErrCode(self.l)) 154 default: 155 return "" 156 } 157 }