This commit is contained in:
RPRX 2020-11-25 19:01:53 +08:00
parent 47d23e9972
commit c7f7c08ead
711 changed files with 82154 additions and 2 deletions

View file

@ -0,0 +1,45 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"github.com/xtls/xray-core/v1/common"
)
func main() {
pwd, err := os.Getwd()
if err != nil {
fmt.Println("can not get current working directory")
os.Exit(1)
}
pkg := filepath.Base(pwd)
if pkg == "xray-core" {
pkg = "core"
}
moduleName, gmnErr := common.GetModuleName(pwd)
if gmnErr != nil {
fmt.Println("can not get module path", gmnErr)
os.Exit(1)
}
file, err := os.OpenFile("errors.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
log.Fatalf("Failed to generate errors.generated.go: %v", err)
os.Exit(1)
}
defer file.Close()
fmt.Fprintln(file, "package", pkg)
fmt.Fprintln(file, "")
fmt.Fprintln(file, "import \""+moduleName+"/common/errors\"")
fmt.Fprintln(file, "")
fmt.Fprintln(file, "type errPathObjHolder struct{}")
fmt.Fprintln(file, "")
fmt.Fprintln(file, "func newError(values ...interface{}) *errors.Error {")
fmt.Fprintln(file, " return errors.New(values...).WithPathObj(errPathObjHolder{})")
fmt.Fprintln(file, "}")
}

195
common/errors/errors.go Normal file
View file

@ -0,0 +1,195 @@
// Package errors is a drop-in replacement for Golang lib 'errors'.
package errors // import "github.com/xtls/xray-core/v1/common/errors"
import (
"os"
"reflect"
"strings"
"github.com/xtls/xray-core/v1/common/log"
"github.com/xtls/xray-core/v1/common/serial"
)
type hasInnerError interface {
// Inner returns the underlying error of this one.
Inner() error
}
type hasSeverity interface {
Severity() log.Severity
}
// Error is an error object with underlying error.
type Error struct {
pathObj interface{}
prefix []interface{}
message []interface{}
inner error
severity log.Severity
}
func (err *Error) WithPathObj(obj interface{}) *Error {
err.pathObj = obj
return err
}
func (err *Error) pkgPath() string {
if err.pathObj == nil {
return ""
}
return reflect.TypeOf(err.pathObj).PkgPath()
}
// Error implements error.Error().
func (err *Error) Error() string {
builder := strings.Builder{}
for _, prefix := range err.prefix {
builder.WriteByte('[')
builder.WriteString(serial.ToString(prefix))
builder.WriteString("] ")
}
path := err.pkgPath()
if len(path) > 0 {
builder.WriteString(path)
builder.WriteString(": ")
}
msg := serial.Concat(err.message...)
builder.WriteString(msg)
if err.inner != nil {
builder.WriteString(" > ")
builder.WriteString(err.inner.Error())
}
return builder.String()
}
// Inner implements hasInnerError.Inner()
func (err *Error) Inner() error {
if err.inner == nil {
return nil
}
return err.inner
}
func (err *Error) Base(e error) *Error {
err.inner = e
return err
}
func (err *Error) atSeverity(s log.Severity) *Error {
err.severity = s
return err
}
func (err *Error) Severity() log.Severity {
if err.inner == nil {
return err.severity
}
if s, ok := err.inner.(hasSeverity); ok {
as := s.Severity()
if as < err.severity {
return as
}
}
return err.severity
}
// AtDebug sets the severity to debug.
func (err *Error) AtDebug() *Error {
return err.atSeverity(log.Severity_Debug)
}
// AtInfo sets the severity to info.
func (err *Error) AtInfo() *Error {
return err.atSeverity(log.Severity_Info)
}
// AtWarning sets the severity to warning.
func (err *Error) AtWarning() *Error {
return err.atSeverity(log.Severity_Warning)
}
// AtError sets the severity to error.
func (err *Error) AtError() *Error {
return err.atSeverity(log.Severity_Error)
}
// String returns the string representation of this error.
func (err *Error) String() string {
return err.Error()
}
// WriteToLog writes current error into log.
func (err *Error) WriteToLog(opts ...ExportOption) {
var holder ExportOptionHolder
for _, opt := range opts {
opt(&holder)
}
if holder.SessionID > 0 {
err.prefix = append(err.prefix, holder.SessionID)
}
log.Record(&log.GeneralMessage{
Severity: GetSeverity(err),
Content: err,
})
}
type ExportOptionHolder struct {
SessionID uint32
}
type ExportOption func(*ExportOptionHolder)
// New returns a new error object with message formed from given arguments.
func New(msg ...interface{}) *Error {
return &Error{
message: msg,
severity: log.Severity_Info,
}
}
// Cause returns the root cause of this error.
func Cause(err error) error {
if err == nil {
return nil
}
L:
for {
switch inner := err.(type) {
case hasInnerError:
if inner.Inner() == nil {
break L
}
err = inner.Inner()
case *os.PathError:
if inner.Err == nil {
break L
}
err = inner.Err
case *os.SyscallError:
if inner.Err == nil {
break L
}
err = inner.Err
default:
break L
}
}
return err
}
// GetSeverity returns the actual severity of the error, including inner errors.
func GetSeverity(err error) log.Severity {
if s, ok := err.(hasSeverity); ok {
return s.Severity()
}
return log.Severity_Info
}

View file

@ -0,0 +1,62 @@
package errors_test
import (
"io"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/v1/common/errors"
"github.com/xtls/xray-core/v1/common/log"
)
func TestError(t *testing.T) {
err := New("TestError")
if v := GetSeverity(err); v != log.Severity_Info {
t.Error("severity: ", v)
}
err = New("TestError2").Base(io.EOF)
if v := GetSeverity(err); v != log.Severity_Info {
t.Error("severity: ", v)
}
err = New("TestError3").Base(io.EOF).AtWarning()
if v := GetSeverity(err); v != log.Severity_Warning {
t.Error("severity: ", v)
}
err = New("TestError4").Base(io.EOF).AtWarning()
err = New("TestError5").Base(err)
if v := GetSeverity(err); v != log.Severity_Warning {
t.Error("severity: ", v)
}
if v := err.Error(); !strings.Contains(v, "EOF") {
t.Error("error: ", v)
}
}
type e struct{}
func TestErrorMessage(t *testing.T) {
data := []struct {
err error
msg string
}{
{
err: New("a").Base(New("b")).WithPathObj(e{}),
msg: "github.com/xtls/xray-core/v1/common/errors_test: a > b",
},
{
err: New("a").Base(New("b").WithPathObj(e{})),
msg: "a > github.com/xtls/xray-core/v1/common/errors_test: b",
},
}
for _, d := range data {
if diff := cmp.Diff(d.msg, d.err.Error()); diff != "" {
t.Error(diff)
}
}
}

View file

@ -0,0 +1,30 @@
package errors
import (
"strings"
)
type multiError []error
func (e multiError) Error() string {
var r strings.Builder
r.WriteString("multierr: ")
for _, err := range e {
r.WriteString(err.Error())
r.WriteString(" | ")
}
return r.String()
}
func Combine(maybeError ...error) error {
var errs multiError
for _, err := range maybeError {
if err != nil {
errs = append(errs, err)
}
}
if len(errs) == 0 {
return nil
}
return errs
}