/
init.go
180 lines (166 loc) · 5.08 KB
/
init.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package verror
import "v.io/v23/vdl"
func init() {
// TODO(bprosnitz) Remove this old-style registration.
// We must register the error conversion functions between vdl.WireError and
// the standard error interface with the vdl package. This allows the vdl
// package to have minimal dependencies.
vdl.RegisterNativeError(WireToNative, WireFromNative)
// New-style error registration.
vdl.RegisterNative(ErrorToNative, ErrorFromNative)
}
// TODO(toddw): rename Error{To,From}Native to Wire{To,From}Native, after we've
// switched to the new vdl Encoder/Decoder, and the old functions are no longer
// used.
// ErrorToNative converts from the wire to native representation of errors.
func ErrorToNative(wire *vdl.WireError, native *error) error {
if wire == nil {
*native = nil
return nil
}
e := new(E)
*native = e
return WireToNative(*wire, e)
}
// ErrorFromNative converts from the native to wire representation of errors.
func ErrorFromNative(wire **vdl.WireError, native error) error {
if native == nil {
*wire = nil
return nil
}
if *wire == nil {
*wire = new(vdl.WireError)
}
return WireFromNative(*wire, native)
}
// FromWire is a convenience for generated code to convert wire errors into
// native errors.
func FromWire(wire *vdl.WireError) error {
var native error
if err := ErrorToNative(wire, &native); err != nil {
native = err
}
return native
}
// WireToNative converts from vdl.WireError to verror.E, which
// implements the standard go error interface.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireToNative(wire vdl.WireError, native *E) error {
*native = E{
ID: ID(wire.Id),
Action: retryToAction(wire.RetryCode),
Msg: wire.Msg,
}
for _, pWire := range wire.ParamList {
var pNative interface{}
if err := vdl.Convert(&pNative, pWire); err != nil {
// It's questionable what to do if the conversion fails, rather than
// ending up with a native Go value.
//
// At the moment, we plug the *vdl.Value into the native params. The idea
// is that this will still be more useful to the user, since they'll still
// have the error Id and Action.
//
// TODO(toddw): Consider whether there is a better strategy.
pNative = pWire
}
native.ParamList = append(native.ParamList, pNative)
}
return nil
}
// WireFromNative converts from the standard go error interface to
// verror.E, and then to vdl.WireError.
//
// TODO(toddw): Remove this function after the switch to the new vdl
// Encoder/Decoder is complete.
func WireFromNative(wire *vdl.WireError, native error) error {
e := ExplicitConvert(ErrUnknown, "", "", "", native)
*wire = vdl.WireError{
Id: string(ErrorID(e)),
RetryCode: retryFromAction(Action(e)),
Msg: e.Error(),
}
for _, pNative := range params(e) {
var pWire *vdl.Value
if err := vdl.Convert(&pWire, pNative); err != nil {
// It's questionable what to do here if the conversion fails, similarly to
// the conversion failure above in WireToNative.
//
// TODO(toddw): Consider whether there is a better strategy.
pWire = vdl.StringValue(nil, err.Error())
}
wire.ParamList = append(wire.ParamList, pWire)
}
return nil
}
func retryToAction(retry vdl.WireRetryCode) ActionCode {
switch retry {
case vdl.WireRetryCodeNoRetry:
return NoRetry
case vdl.WireRetryCodeRetryConnection:
return RetryConnection
case vdl.WireRetryCodeRetryRefetch:
return RetryRefetch
case vdl.WireRetryCodeRetryBackoff:
return RetryBackoff
}
// Backoff to no retry by default.
return NoRetry
}
func retryFromAction(action ActionCode) vdl.WireRetryCode {
switch action.RetryAction() {
case NoRetry:
return vdl.WireRetryCodeNoRetry
case RetryConnection:
return vdl.WireRetryCodeRetryConnection
case RetryRefetch:
return vdl.WireRetryCodeRetryRefetch
case RetryBackoff:
return vdl.WireRetryCodeRetryBackoff
}
// Backoff to no retry by default.
return vdl.WireRetryCodeNoRetry
}
// VDLRead implements the logic to read x from dec.
//
// Unlike regular VDLRead implementations, this handles the case where the
// decoder contains a nil value, to make code generation simpler.
func VDLRead(dec vdl.Decoder, x *error) error {
if err := dec.StartValue(vdl.ErrorType.Elem()); err != nil {
return err
}
if dec.IsNil() {
*x = nil
return dec.FinishValue()
}
dec.IgnoreNextStartValue()
var wire vdl.WireError
if err := wire.VDLRead(dec); err != nil {
return err
}
nativePtr := new(E)
if err := WireToNative(wire, nativePtr); err != nil {
return err
}
*x = nativePtr
return nil
}
// VDLWrite implements the logic to write x to enc.
//
// Unlike regular VDLWrite implementations, this handles the case where x
// contains a nil value, to make code generation simpler.
func VDLWrite(enc vdl.Encoder, x error) error {
if x == nil {
return enc.NilValue(vdl.ErrorType)
}
var wire vdl.WireError
if err := WireFromNative(&wire, x); err != nil {
return err
}
return wire.VDLWrite(enc)
}