-
Notifications
You must be signed in to change notification settings - Fork 1
/
return.go
102 lines (78 loc) · 1.79 KB
/
return.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
package salt
import (
"encoding/json"
"fmt"
"io"
"reflect"
)
type Format int
const (
FormatObject Format = iota
FormatRunner
)
type ReturnFunc func(string, Response) error
func readReturn(r io.Reader, fn ReturnFunc, format Format) error {
dec := json.NewDecoder(r)
// Object return:
// { "return": [ { string(<id>): object(<value>), ... } ] }
//
// Runner return:
// { "return": [ <value> ] }
var tokens = []json.Token{
json.Delim('{'),
json.Token("return"),
json.Delim('['),
}
if format == FormatObject {
tokens = append(tokens, json.Delim('{'))
}
if err := readTokens(dec, tokens); err != nil {
return err
}
// The data buffer is reused to minimize allocations.
var data Response
for dec.More() {
var id string
if format == FormatObject {
t, err := dec.Token()
if err != nil {
return err
}
v, ok := t.(string)
if !ok {
return fmt.Errorf("expected string, received %s", t)
}
id = v
}
if err := dec.Decode(&data); err != nil {
return err
}
if fn != nil {
if err := fn(id, data); err != nil {
return err
}
}
}
switch format {
case FormatObject:
tokens = []json.Token{json.Delim('}'), json.Delim(']'), json.Delim('}')}
case FormatRunner:
tokens = []json.Token{json.Delim(']'), json.Delim('}')}
}
return readTokens(dec, tokens)
}
// readTokens reads the expected sequence of JSON tokens from the decoder,
// returning an error if not all tokens were able to be read, or an unexpected
// token is encountered.
func readTokens(dec *json.Decoder, seq []json.Token) error {
var err error
var tok json.Token
for _, exp := range seq {
tok, err = dec.Token()
if !reflect.DeepEqual(exp, tok) {
return fmt.Errorf("expected %v (%T), received %v (%T), error %v",
exp, exp, tok, tok, err)
}
}
return err
}