Skip to content

Commit eba4f1d

Browse files
author
Lingyu Song
authored
add standard error library (pkg#24)
1 parent 4e113dd commit eba4f1d

File tree

6 files changed

+124
-569
lines changed

6 files changed

+124
-569
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# Folders
77
_obj
88
_test
9+
.idea
910

1011
# Architecture specific extensions/prefixes
1112
*.[568vq]

terror_dsl.go

Lines changed: 0 additions & 73 deletions
This file was deleted.

terror_error.go

Lines changed: 107 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ import (
2121
"strings"
2222
)
2323

24+
// ErrCode represents a specific error type in a error class.
25+
// Same error code can be used in different error classes.
26+
type ErrCode int
27+
28+
// ErrCodeText is a textual error code that represents a specific error type in a error class.
29+
type ErrCodeText string
30+
31+
type ErrorID string
32+
type RFCErrorCode string
33+
2434
// Error is the 'prototype' of a type of errors.
2535
// Use DefineError to make a *Error:
2636
// var ErrUnavailable = ClassRegion.DefineError().
@@ -46,29 +56,25 @@ import (
4656
// // handle this error.
4757
// }
4858
type Error struct {
49-
class *ErrClass
50-
code ErrCode
59+
code ErrCode
5160
// codeText is the textual describe of the error code
5261
codeText ErrCodeText
5362
// message is a template of the description of this error.
5463
// printf-style formatting is enabled.
5564
message string
5665
// The workaround field: how to work around this error.
5766
// It's used to teach the users how to solve the error if occurring in the real environment.
58-
Workaround string
67+
workaround string
5968
// Description is the expanded detail of why this error occurred.
6069
// This could be written by developer at a static env,
6170
// and the more detail this field explaining the better,
6271
// even some guess of the cause could be included.
63-
Description string
64-
args []interface{}
65-
file string
66-
line int
67-
}
68-
69-
// Class returns ErrClass
70-
func (e *Error) Class() *ErrClass {
71-
return e.class
72+
description string
73+
// Cause is used to warp some third party error.
74+
cause error
75+
args []interface{}
76+
file string
77+
line int
7278
}
7379

7480
// Code returns the numeric code of this error.
@@ -84,23 +90,7 @@ func (e *Error) Code() ErrCode {
8490
// The error code is a 3-tuple of abbreviated component name, error class and error code,
8591
// joined by a colon like {Component}:{ErrorClass}:{InnerErrorCode}.
8692
func (e *Error) RFCCode() RFCErrorCode {
87-
ec := e.Class()
88-
if ec == nil {
89-
return RFCErrorCode(e.ID())
90-
}
91-
reg := ec.registry
92-
// Maybe top-level errors.
93-
if reg.Name == "" {
94-
return RFCErrorCode(fmt.Sprintf("%s:%s",
95-
ec.Description,
96-
e.ID(),
97-
))
98-
}
99-
return RFCErrorCode(fmt.Sprintf("%s:%s:%s",
100-
reg.Name,
101-
ec.Description,
102-
e.ID(),
103-
))
93+
return RFCErrorCode(e.ID())
10494
}
10595

10696
// ID returns the ID of this error.
@@ -124,14 +114,17 @@ func (e *Error) MessageTemplate() string {
124114

125115
// Error implements error interface.
126116
func (e *Error) Error() string {
117+
if e == nil {
118+
return "<nil>"
119+
}
127120
describe := e.codeText
128121
if len(describe) == 0 {
129122
describe = ErrCodeText(strconv.Itoa(int(e.code)))
130123
}
131-
return fmt.Sprintf("[%s] %s", e.RFCCode(), e.getMsg())
124+
return fmt.Sprintf("[%s]%s", e.RFCCode(), e.GetMsg())
132125
}
133126

134-
func (e *Error) getMsg() string {
127+
func (e *Error) GetMsg() string {
135128
if len(e.args) > 0 {
136129
return fmt.Sprintf(e.message, e.args...)
137130
}
@@ -197,9 +190,8 @@ func (e *Error) Equal(err error) bool {
197190
if !ok {
198191
return false
199192
}
200-
classEquals := e.class.Equal(inErr.class)
201193
idEquals := e.ID() == inErr.ID()
202-
return classEquals && idEquals
194+
return idEquals
203195
}
204196

205197
// NotEqual checks if err is not equal to e.
@@ -239,7 +231,6 @@ type jsonError struct {
239231
Error string `json:"message"`
240232
Description string `json:"description,omitempty"`
241233
Workaround string `json:"workaround,omitempty"`
242-
Class ErrClassID `json:"classID"`
243234
File string `json:"file"`
244235
Line int `json:"line"`
245236
}
@@ -251,11 +242,10 @@ type jsonError struct {
251242
// This function is reserved for compatibility.
252243
func (e *Error) MarshalJSON() ([]byte, error) {
253244
return json.Marshal(&jsonError{
254-
Error: e.getMsg(),
255-
Description: e.Description,
256-
Workaround: e.Workaround,
245+
Error: e.GetMsg(),
246+
Description: e.description,
247+
Workaround: e.workaround,
257248
RFCCode: e.RFCCode(),
258-
Class: e.class.ID,
259249
Line: e.line,
260250
File: e.file,
261251
})
@@ -273,21 +263,90 @@ func (e *Error) UnmarshalJSON(data []byte) error {
273263
return Trace(err)
274264
}
275265
codes := strings.Split(string(err.RFCCode), ":")
276-
regName := codes[0]
277-
className := codes[1]
278-
innerCode := codes[2]
266+
innerCode := codes[len(codes)-1]
279267
if i, errAtoi := strconv.Atoi(innerCode); errAtoi == nil {
280268
e.code = ErrCode(i)
281-
} else {
282-
e.codeText = ErrCodeText(innerCode)
283269
}
270+
e.codeText = ErrCodeText(err.RFCCode)
284271
e.line = err.Line
285272
e.file = err.File
286273
e.message = err.Error
287-
e.class = &ErrClass{
288-
Description: className,
289-
ID: err.Class,
290-
registry: &Registry{Name: regName},
291-
}
292274
return nil
293275
}
276+
277+
func (e *Error) Wrap(err error) *Error {
278+
if err != nil {
279+
newErr := *e
280+
newErr.cause = err
281+
return &newErr
282+
}
283+
return e
284+
}
285+
286+
func (e *Error) Cause() error {
287+
root := Unwrap(e.cause)
288+
if root == nil {
289+
return e.cause
290+
}
291+
return root
292+
}
293+
294+
func (e *Error) FastGenWithCause(args ...interface{}) error {
295+
err := *e
296+
if e.cause != nil {
297+
err.message = e.cause.Error()
298+
}
299+
err.args = args
300+
return SuspendStack(&err)
301+
}
302+
303+
func (e *Error) GenWithStackByCause(args ...interface{}) error {
304+
err := *e
305+
if e.cause != nil {
306+
err.message = e.cause.Error()
307+
}
308+
err.args = args
309+
err.fillLineAndFile(1)
310+
return AddStack(&err)
311+
}
312+
313+
type NormalizeOption func(*Error)
314+
315+
// Description returns a NormalizeOption to set description.
316+
func Description(desc string) NormalizeOption {
317+
return func(e *Error) {
318+
e.description = desc
319+
}
320+
}
321+
322+
// Workaround returns a NormalizeOption to set workaround.
323+
func Workaround(wr string) NormalizeOption {
324+
return func(e *Error) {
325+
e.workaround = wr
326+
}
327+
}
328+
329+
// RFCCodeText returns a NormalizeOption to set RFC error code.
330+
func RFCCodeText(codeText string) NormalizeOption {
331+
return func(e *Error) {
332+
e.codeText = ErrCodeText(codeText)
333+
}
334+
}
335+
336+
// MySQLErrorCode returns a NormalizeOption to set error code.
337+
func MySQLErrorCode(code int) NormalizeOption {
338+
return func(e *Error) {
339+
e.code = ErrCode(code)
340+
}
341+
}
342+
343+
// Normalize creates a new Error object.
344+
func Normalize(message string, opts ...NormalizeOption) *Error {
345+
e := &Error{
346+
message: message,
347+
}
348+
for _, opt := range opts {
349+
opt(e)
350+
}
351+
return e
352+
}

terror_gen.go

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)