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  }