package errs import ( "errors" "backend/pkg/library/errors/code" "google.golang.org/grpc/status" ) func newBuiltinGRPCErr(scope, detail uint32, msg string) *Error { return &Error{ category: uint32(code.CatGRPC), detail: detail, scope: scope, msg: msg, } } // FromError tries to let error as Err // it supports to unwrap error that has Error // return nil if failed to transfer func FromError(err error) *Error { if err == nil { return nil } var e *Error if errors.As(err, &e) { return e } return nil } // FromCode parses code as following 8 碼 // Decimal: 10201000 // 10 represents Scope // 201 represents Category // 000 represents Detail error code func FromCode(code uint32) *Error { const CodeMultiplier = 1000000 const SubMultiplier = 1000 // 獲取 scope,前兩位數 scope := code / CodeMultiplier // 獲取 detail,最後三位數 detail := code % SubMultiplier // 獲取 category,中間三位數 category := (code / SubMultiplier) % SubMultiplier return &Error{ category: category, detail: detail, scope: scope, msg: "", } } // FromGRPCError transfer error to Err // useful for gRPC client func FromGRPCError(err error) *Error { s, _ := status.FromError(err) e := FromCode(uint32(s.Code())) e.msg = s.Message() // For GRPC built-in code if e.Scope() == uint32(code.Unset) && e.Category() == 0 && e.Code() != code.OK { e = newBuiltinGRPCErr(uint32(Scope), e.detail, s.Message()) // Note: detail is now 3-digit, but built-in codes are small } return e }