|
1 | 1 | package tarantool
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "errors" |
5 | 4 | "fmt"
|
6 | 5 | "gopkg.in/vmihailenco/msgpack.v2"
|
7 |
| - "io" |
8 | 6 | )
|
9 | 7 |
|
10 | 8 | type Response struct {
|
11 | 9 | RequestId uint32
|
12 | 10 | Code uint32
|
13 |
| - Error error |
| 11 | + Error string |
14 | 12 | Data []interface{}
|
| 13 | + buf smallBuf |
15 | 14 | }
|
16 | 15 |
|
17 |
| -type responseAndError struct { |
18 |
| - c chan struct{} |
19 |
| - b []byte |
20 |
| - r Response |
| 16 | +func (resp *Response) fill(b []byte) { |
| 17 | + resp.buf.b = b |
21 | 18 | }
|
22 | 19 |
|
23 |
| -type smallBuf struct { |
24 |
| - b []byte |
25 |
| - p int |
| 20 | +func newResponse(b []byte) (resp *Response, err error) { |
| 21 | + resp = &Response{ buf: smallBuf{b: b} } |
| 22 | + err = resp.decodeHeader() |
| 23 | + return |
26 | 24 | }
|
27 | 25 |
|
28 |
| -func (s *smallBuf) Read(d []byte) (l int, err error) { |
29 |
| - l = len(s.b) - s.p |
30 |
| - if l == 0 && len(d) > 0 { |
31 |
| - return 0, io.EOF |
32 |
| - } |
33 |
| - if l > len(d) { |
34 |
| - l = len(d) |
35 |
| - } |
36 |
| - copy(d, s.b[s.p:]) |
37 |
| - s.p += l |
38 |
| - return l, nil |
39 |
| -} |
40 |
| - |
41 |
| -func (s *smallBuf) ReadByte() (b byte, err error) { |
42 |
| - if s.p == len(s.b) { |
43 |
| - return 0, io.EOF |
44 |
| - } |
45 |
| - b = s.b[s.p] |
46 |
| - s.p++ |
47 |
| - return b, nil |
48 |
| -} |
49 |
| - |
50 |
| -func (s *smallBuf) UnreadByte() error { |
51 |
| - if s.p == 0 { |
52 |
| - return errors.New("Could not unread") |
53 |
| - } |
54 |
| - s.p-- |
55 |
| - return nil |
56 |
| -} |
57 |
| - |
58 |
| -func (s *smallBuf) Len() int { |
59 |
| - return len(s.b) - s.p |
60 |
| -} |
61 |
| - |
62 |
| -func (s *smallBuf) Bytes() []byte { |
63 |
| - if len(s.b) > s.p { |
64 |
| - return s.b[s.p:] |
65 |
| - } |
66 |
| - return nil |
67 |
| -} |
68 |
| - |
69 |
| -func (r *Response) fill(b []byte) []byte { |
| 26 | +func (resp *Response) decodeHeader() (err error) { |
70 | 27 | var l int
|
71 |
| - s := smallBuf{b: b} |
72 |
| - d := msgpack.NewDecoder(&s) |
73 |
| - if l, r.Error = d.DecodeMapLen(); r.Error != nil { |
74 |
| - return nil |
| 28 | + d := msgpack.NewDecoder(&resp.buf) |
| 29 | + if l, err = d.DecodeMapLen(); err != nil { |
| 30 | + return |
75 | 31 | }
|
76 | 32 | for ; l > 0; l-- {
|
77 | 33 | var cd int
|
78 |
| - if cd, r.Error = d.DecodeInt(); r.Error != nil { |
79 |
| - return nil |
| 34 | + if cd, err = d.DecodeInt(); err != nil { |
| 35 | + return |
80 | 36 | }
|
81 | 37 | switch cd {
|
82 | 38 | case KeySync:
|
83 |
| - if r.RequestId, r.Error = d.DecodeUint32(); r.Error != nil { |
84 |
| - return nil |
| 39 | + if resp.RequestId, err = d.DecodeUint32(); err != nil { |
| 40 | + return |
85 | 41 | }
|
86 | 42 | case KeyCode:
|
87 |
| - if r.Code, r.Error = d.DecodeUint32(); r.Error != nil { |
88 |
| - return nil |
| 43 | + if resp.Code, err = d.DecodeUint32(); err != nil { |
| 44 | + return |
89 | 45 | }
|
90 | 46 | }
|
91 | 47 | }
|
92 |
| - return s.Bytes() |
93 |
| -} |
94 |
| - |
95 |
| -func (resp *Response) String() (str string) { |
96 |
| - if resp.Code == OkCode { |
97 |
| - return fmt.Sprintf("<%d OK %v>", resp.RequestId, resp.Data) |
98 |
| - } else { |
99 |
| - return fmt.Sprintf("<%d ERR 0x%x %s>", resp.RequestId, resp.Code, resp.Error) |
100 |
| - } |
| 48 | + return nil |
101 | 49 | }
|
102 | 50 |
|
103 |
| -func (r *responseAndError) get() (*Response, error) { |
104 |
| - if r.r.Error != nil { |
105 |
| - return &r.r, r.r.Error |
106 |
| - } |
107 |
| - if len(r.b) > 0 { |
| 51 | +func (resp *Response) decodeBody() (err error) { |
| 52 | + if len(resp.buf.Len()) > 2 { |
108 | 53 | var body map[int]interface{}
|
109 |
| - d := msgpack.NewDecoder(&smallBuf{b: r.b}) |
| 54 | + d := msgpack.NewDecoder(&resp.buf) |
110 | 55 |
|
111 |
| - if r.r.Error = d.Decode(&body); r.r.Error != nil { |
112 |
| - r.b = nil |
113 |
| - return nil, r.r.Error |
| 56 | + if err = d.Decode(&body); err != nil { |
| 57 | + return nil, err |
114 | 58 | }
|
115 | 59 |
|
116 | 60 | if body[KeyData] != nil {
|
117 | 61 | data := body[KeyData].([]interface{})
|
118 |
| - r.r.Data = make([]interface{}, len(data)) |
| 62 | + resp.Data = make([]interface{}, len(data)) |
119 | 63 | for i, v := range data {
|
120 |
| - r.r.Data[i] = v.([]interface{}) |
| 64 | + resp.Data[i] = v.([]interface{}) |
121 | 65 | }
|
122 | 66 | }
|
123 | 67 |
|
124 |
| - if r.r.Code != OkCode { |
125 |
| - r.r.Error = Error{r.r.Code, body[KeyError].(string)} |
| 68 | + if resp.Code != OkCode { |
| 69 | + err = Error{resp.Code, body[KeyError].(string)} |
126 | 70 | }
|
127 |
| - r.b = nil |
128 | 71 | }
|
129 |
| - |
130 |
| - return &r.r, r.r.Error |
131 | 72 | }
|
132 | 73 |
|
133 |
| -func (r *responseAndError) getTyped(res interface{}) error { |
134 |
| - if r.r.Error != nil { |
135 |
| - return r.r.Error |
136 |
| - } |
137 |
| - if len(r.b) > 0 { |
| 74 | +func (resp *Response) decodeBodyTyped(res interface{}) (err error) { |
| 75 | + if len(resp.buf.Len()) > 0 { |
138 | 76 | var l int
|
139 |
| - d := msgpack.NewDecoder(&smallBuf{b: r.b}) |
140 |
| - if l, r.r.Error = d.DecodeMapLen(); r.r.Error != nil { |
141 |
| - r.b = nil |
142 |
| - return r.r.Error |
| 77 | + d := msgpack.NewDecoder(&resp.buf) |
| 78 | + if l, err = d.DecodeMapLen(); err != nil { |
| 79 | + return err |
143 | 80 | }
|
144 | 81 |
|
145 | 82 | for ; l > 0; l-- {
|
146 | 83 | var cd int
|
147 |
| - if cd, r.r.Error = d.DecodeInt(); r.r.Error != nil { |
148 |
| - r.b = nil |
149 |
| - return r.r.Error |
| 84 | + if cd, err = d.DecodeInt(); err != nil { |
| 85 | + return err |
150 | 86 | }
|
151 | 87 | switch cd {
|
152 | 88 | case KeyData:
|
153 |
| - if r.r.Error = d.Decode(res); r.r.Error != nil { |
154 |
| - r.b = nil |
155 |
| - return r.r.Error |
| 89 | + if err = d.Decode(res); err != nil { |
| 90 | + return err |
156 | 91 | }
|
157 | 92 | case KeyError:
|
158 |
| - var str string |
159 |
| - if str, r.r.Error = d.DecodeString(); r.r.Error == nil { |
160 |
| - r.r.Error = Error{ |
161 |
| - r.r.Code, |
162 |
| - str, |
163 |
| - } |
| 93 | + if resp.Error, err = d.DecodeString(); err != nil { |
| 94 | + return err |
164 | 95 | }
|
165 |
| - r.b = nil |
166 |
| - return r.r.Error |
167 | 96 | }
|
168 | 97 | }
|
| 98 | + |
| 99 | + if resp.Code != OkCode { |
| 100 | + err = Error{resp.Code, body[KeyError].(string)} |
| 101 | + } |
169 | 102 | }
|
| 103 | + return |
| 104 | +} |
170 | 105 |
|
171 |
| - return r.r.Error |
| 106 | +func (resp *Response) String() (str string) { |
| 107 | + if resp.Code == OkCode { |
| 108 | + return fmt.Sprintf("<%d OK %v>", resp.RequestId, resp.Data) |
| 109 | + } else { |
| 110 | + return fmt.Sprintf("<%d ERR 0x%x %s>", resp.RequestId, resp.Code, resp.Error) |
| 111 | + } |
172 | 112 | }
|
0 commit comments