forked from mission-liao/dingo
/
marshaller_gob.go
148 lines (126 loc) · 2.79 KB
/
marshaller_gob.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
package dingo
import (
"bytes"
"encoding/gob"
"errors"
"fmt"
"reflect"
)
/*GobMarshaller is a marshaller implemented via gob encoding.
Note: this Marshaller can work with both GenericInvoker and LazyInvoker.
*/
type GobMarshaller struct{}
func (ms *GobMarshaller) Prepare(name string, fn interface{}) (err error) {
var (
fT reflect.Type
)
// Gob needs to register type before encode/decode
if fT = reflect.TypeOf(fn); fT.Kind() != reflect.Func {
err = fmt.Errorf("fn is not a function but %v", fn)
return
}
reg := func(v reflect.Value) (err error) {
if !v.CanInterface() {
err = fmt.Errorf("Can't convert to value in input of %v for name:%v", fn, name)
return
}
gob.Register(v.Interface())
return
}
for i := 0; i < fT.NumIn(); i++ {
// create a zero value of the type of parameters
if err = reg(reflect.Zero(fT.In(i))); err != nil {
return
}
}
for i := 0; i < fT.NumOut(); i++ {
if err = reg(reflect.Zero(fT.Out(i))); err != nil {
return
}
}
return
}
func (ms *GobMarshaller) EncodeTask(fn interface{}, task *Task) (b []byte, err error) {
if task == nil {
err = errors.New("nil is bad for Gob")
return
}
// reset registry
task.H.Reset()
// encode header
var bHead []byte
if bHead, err = task.H.Flush(0); err != nil {
return
}
// encode payload
var buff = bytes.NewBuffer(bHead)
if err = gob.NewEncoder(buff).Encode(task.P); err == nil {
b = buff.Bytes()
}
return
}
func (ms *GobMarshaller) DecodeTask(h *Header, fn interface{}, b []byte) (task *Task, err error) {
// decode header
if h == nil {
if h, err = DecodeHeader(b); err != nil {
return
}
}
// clean registry when leaving
defer func() {
if h != nil {
h.Reset()
}
}()
// decode payload
var payload *TaskPayload
if err = gob.NewDecoder(bytes.NewBuffer(b[h.Length():])).Decode(&payload); err == nil {
task = &Task{
H: h,
P: payload,
}
}
return
}
func (ms *GobMarshaller) EncodeReport(fn interface{}, report *Report) (b []byte, err error) {
if report == nil {
err = errors.New("nil is bad for Gob")
return
}
// reset registry
report.H.Reset()
// encode header
var bHead []byte
if bHead, err = report.H.Flush(0); err != nil {
return
}
// encode payload
var buff = bytes.NewBuffer(bHead)
if err = gob.NewEncoder(buff).Encode(report.P); err == nil {
b = buff.Bytes()
}
return
}
func (ms *GobMarshaller) DecodeReport(h *Header, fn interface{}, b []byte) (report *Report, err error) {
// decode header
if h == nil {
if h, err = DecodeHeader(b); err != nil {
return
}
}
// clean registry when leaving
defer func() {
if h != nil {
h.Reset()
}
}()
// decode payload
var payload *ReportPayload
if err = gob.NewDecoder(bytes.NewBuffer(b[h.Length():])).Decode(&payload); err == nil {
report = &Report{
H: h,
P: payload,
}
}
return
}