forked from tarantool/go-tarantool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresponse.go
128 lines (119 loc) · 2.45 KB
/
response.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
package tarantool
import (
"fmt"
"gopkg.in/vmihailenco/msgpack.v2"
)
type Response struct {
RequestId uint32
Code uint32
Error string
Data []interface{}
buf smallBuf
}
func (resp *Response) fill(b []byte) {
resp.buf.b = b
}
func newResponse(b []byte) (resp *Response, err error) {
resp = &Response{buf: smallBuf{b: b}}
err = resp.decodeHeader()
return
}
func (resp *Response) decodeHeader() (err error) {
var l int
d := msgpack.NewDecoder(&resp.buf)
if l, err = d.DecodeMapLen(); err != nil {
return
}
for ; l > 0; l-- {
var cd int
if cd, err = d.DecodeInt(); err != nil {
return
}
switch cd {
case KeySync:
if resp.RequestId, err = d.DecodeUint32(); err != nil {
return
}
case KeyCode:
if resp.Code, err = d.DecodeUint32(); err != nil {
return
}
default:
if _, err = d.DecodeInterface(); err != nil {
return
}
}
}
return nil
}
func (resp *Response) decodeBody() (err error) {
if resp.buf.Len() > 2 {
var body map[int]interface{}
d := msgpack.NewDecoder(&resp.buf)
if err = d.Decode(&body); err != nil {
return err
}
if body[KeyData] != nil {
resp.Data = body[KeyData].([]interface{})
}
if body[KeyError] != nil {
resp.Error = body[KeyError].(string)
}
if resp.Code != OkCode {
err = Error{resp.Code, resp.Error}
}
}
return
}
func (resp *Response) decodeBodyTyped(res interface{}) (err error) {
if resp.buf.Len() > 0 {
var l int
d := msgpack.NewDecoder(&resp.buf)
if l, err = d.DecodeMapLen(); err != nil {
return err
}
for ; l > 0; l-- {
var cd int
if cd, err = d.DecodeInt(); err != nil {
return err
}
switch cd {
case KeyData:
if err = d.Decode(res); err != nil {
return err
}
case KeyError:
if resp.Error, err = d.DecodeString(); err != nil {
return err
}
default:
if _, err = d.DecodeInterface(); err != nil {
return err
}
}
}
if resp.Code != OkCode {
err = Error{resp.Code, resp.Error}
}
}
return
}
func (resp *Response) String() (str string) {
if resp.Code == OkCode {
return fmt.Sprintf("<%d OK %v>", resp.RequestId, resp.Data)
} else {
return fmt.Sprintf("<%d ERR 0x%x %s>", resp.RequestId, resp.Code, resp.Error)
}
}
func (resp *Response) Tuples() (res [][]interface{}) {
res = make([][]interface{}, len(resp.Data))
for i, t := range resp.Data {
switch t := t.(type) {
case []interface{}:
res[i] = t
default:
res[i] = []interface{}{t}
}
}
return res
}