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 lineBuf := bytes.NewBuffer(line)
84 dec := json.NewDecoder(lineBuf)
85 dec.UseNumber()
86 val, err := decodeJSONValue(dec)
87 if err == nil && val.atom == json.Delim('{') {
88
89 found := false
90 for i := 0; i < len(val.seq); i += 2 {
91 if val.seq[i].atom == "Package" {
92 if pkg, ok := val.seq[i+1].atom.(string); ok {
93 val.seq[i+1].atom = pkg + ":" + f.variant
94 found = true
95 break
96 }
97 }
98 }
99 if found {
100 data, err := json.Marshal(val)
101 if err != nil {
102
103 panic(fmt.Sprintf("failed to round-trip JSON %q: %s", line, err))
104 }
105 f.w.Write(data)
106
107
108 io.Copy(f.w, dec.Buffered())
109 io.Copy(f.w, lineBuf)
110 return
111 }
112 }
113 }
114
115
116 f.w.Write(line)
117 }
118
119 type jsonValue struct {
120 atom json.Token
121 seq []jsonValue
122 }
123
124 var jsonPop = errors.New("end of JSON sequence")
125
126 func decodeJSONValue(dec *json.Decoder) (jsonValue, error) {
127 t, err := dec.Token()
128 if err != nil {
129 if err == io.EOF {
130 err = io.ErrUnexpectedEOF
131 }
132 return jsonValue{}, err
133 }
134
135 switch t := t.(type) {
136 case json.Delim:
137 if t == '}' || t == ']' {
138 return jsonValue{}, jsonPop
139 }
140
141 var seq []jsonValue
142 for {
143 val, err := decodeJSONValue(dec)
144 if err == jsonPop {
145 break
146 } else if err != nil {
147 return jsonValue{}, err
148 }
149 seq = append(seq, val)
150 }
151 return jsonValue{t, seq}, nil
152 default:
153 return jsonValue{t, nil}, nil
154 }
155 }
156
157 func (v jsonValue) MarshalJSON() ([]byte, error) {
158 var buf bytes.Buffer
159 var marshal1 func(v jsonValue) error
160 marshal1 = func(v jsonValue) error {
161 if t, ok := v.atom.(json.Delim); ok {
162 buf.WriteRune(rune(t))
163 for i, v2 := range v.seq {
164 if t == '{' && i%2 == 1 {
165 buf.WriteByte(':')
166 } else if i > 0 {
167 buf.WriteByte(',')
168 }
169 if err := marshal1(v2); err != nil {
170 return err
171 }
172 }
173 if t == '{' {
174 buf.WriteByte('}')
175 } else {
176 buf.WriteByte(']')
177 }
178 return nil
179 }
180 bytes, err := json.Marshal(v.atom)
181 if err != nil {
182 return err
183 }
184 buf.Write(bytes)
185 return nil
186 }
187 err := marshal1(v)
188 return buf.Bytes(), err
189 }
190
191 func synthesizeSkipEvent(enc *json.Encoder, pkg, msg string) {
192 type event struct {
193 Time time.Time
194 Action string
195 Package string
196 Output string `json:",omitempty"`
197 }
198 ev := event{Time: time.Now(), Package: pkg, Action: "start"}
199 enc.Encode(ev)
200 ev.Action = "output"
201 ev.Output = msg
202 enc.Encode(ev)
203 ev.Action = "skip"
204 ev.Output = ""
205 enc.Encode(ev)
206 }
207
View as plain text