Source file
src/cmd/dist/testjson.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "encoding/json"
10 "errors"
11 "fmt"
12 "io"
13 "sync"
14 "time"
15 )
16
17
18 type lockedWriter struct {
19 lock sync.Mutex
20 w io.Writer
21 }
22
23 func (w *lockedWriter) Write(b []byte) (int, error) {
24 w.lock.Lock()
25 defer w.lock.Unlock()
26 return w.w.Write(b)
27 }
28
29
30
31 type testJSONFilter struct {
32 w io.Writer
33 variant string
34
35 lineBuf bytes.Buffer
36 }
37
38 func (f *testJSONFilter) Write(b []byte) (int, error) {
39 bn := len(b)
40
41
42 for len(b) > 0 {
43 nl := bytes.IndexByte(b, '\n')
44 if nl < 0 {
45 f.lineBuf.Write(b)
46 break
47 }
48 var line []byte
49 if f.lineBuf.Len() > 0 {
50
51
52 f.lineBuf.Write(b[:nl+1])
53 line = f.lineBuf.Bytes()
54 } else {
55
56 line = b[:nl+1]
57 }
58 b = b[nl+1:]
59 f.process(line)
60 f.lineBuf.Reset()
61 }
62
63 return bn, nil
64 }
65
66 func (f *testJSONFilter) Flush() {
67
68 if f.lineBuf.Len() > 0 {
69 f.w.Write(f.lineBuf.Bytes())
70 f.lineBuf.Reset()
71 }
72 }
73
74 func (f *testJSONFilter) process(line []byte) {
75 if len(line) > 0 && line[0] == '{' {
76
77
78
79
80
81
82
83 dec := json.NewDecoder(bytes.NewBuffer(line))
84 dec.UseNumber()
85 val, err := decodeJSONValue(dec)
86 if err == nil && val.atom == json.Delim('{') {
87
88 found := false
89 for i := 0; i < len(val.seq); i += 2 {
90 if val.seq[i].atom == "Package" {
91 if pkg, ok := val.seq[i+1].atom.(string); ok {
92 val.seq[i+1].atom = pkg + ":" + f.variant
93 found = true
94 break
95 }
96 }
97 }
98 if found {
99 data, err := json.Marshal(val)
100 if err != nil {
101
102 panic(fmt.Sprintf("failed to round-trip JSON %q: %s", line, err))
103 }
104 f.w.Write(data)
105
106
107 io.Copy(f.w, dec.Buffered())
108 return
109 }
110 }
111 }
112
113
114 f.w.Write(line)
115 }
116
117 type jsonValue struct {
118 atom json.Token
119 seq []jsonValue
120 }
121
122 var jsonPop = errors.New("end of JSON sequence")
123
124 func decodeJSONValue(dec *json.Decoder) (jsonValue, error) {
125 t, err := dec.Token()
126 if err != nil {
127 if err == io.EOF {
128 err = io.ErrUnexpectedEOF
129 }
130 return jsonValue{}, err
131 }
132
133 switch t := t.(type) {
134 case json.Delim:
135 if t == '}' || t == ']' {
136 return jsonValue{}, jsonPop
137 }
138
139 var seq []jsonValue
140 for {
141 val, err := decodeJSONValue(dec)
142 if err == jsonPop {
143 break
144 } else if err != nil {
145 return jsonValue{}, err
146 }
147 seq = append(seq, val)
148 }
149 return jsonValue{t, seq}, nil
150 default:
151 return jsonValue{t, nil}, nil
152 }
153 }
154
155 func (v jsonValue) MarshalJSON() ([]byte, error) {
156 var buf bytes.Buffer
157 var marshal1 func(v jsonValue) error
158 marshal1 = func(v jsonValue) error {
159 if t, ok := v.atom.(json.Delim); ok {
160 buf.WriteRune(rune(t))
161 for i, v2 := range v.seq {
162 if t == '{' && i%2 == 1 {
163 buf.WriteByte(':')
164 } else if i > 0 {
165 buf.WriteByte(',')
166 }
167 if err := marshal1(v2); err != nil {
168 return err
169 }
170 }
171 if t == '{' {
172 buf.WriteByte('}')
173 } else {
174 buf.WriteByte(']')
175 }
176 return nil
177 }
178 bytes, err := json.Marshal(v.atom)
179 if err != nil {
180 return err
181 }
182 buf.Write(bytes)
183 return nil
184 }
185 err := marshal1(v)
186 return buf.Bytes(), err
187 }
188
189 func synthesizeSkipEvent(enc *json.Encoder, pkg, msg string) {
190 type event struct {
191 Time time.Time
192 Action string
193 Package string
194 Output string `json:",omitempty"`
195 }
196 ev := event{Time: time.Now(), Package: pkg, Action: "start"}
197 enc.Encode(ev)
198 ev.Action = "output"
199 ev.Output = msg
200 enc.Encode(ev)
201 ev.Action = "skip"
202 ev.Output = ""
203 enc.Encode(ev)
204 }
205
View as plain text