diff options
author | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
---|---|---|
committer | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
commit | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/golang/protobuf/proto/text.go | |
parent | 07971ca38143c5faf951d152fba370ddcbe26ad5 (diff) | |
download | terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip |
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/github.com/golang/protobuf/proto/text.go')
-rw-r--r-- | vendor/github.com/golang/protobuf/proto/text.go | 843 |
1 files changed, 843 insertions, 0 deletions
diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go new file mode 100644 index 0000000..1aaee72 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text.go | |||
@@ -0,0 +1,843 @@ | |||
1 | // Go support for Protocol Buffers - Google's data interchange format | ||
2 | // | ||
3 | // Copyright 2010 The Go Authors. All rights reserved. | ||
4 | // https://github.com/golang/protobuf | ||
5 | // | ||
6 | // Redistribution and use in source and binary forms, with or without | ||
7 | // modification, are permitted provided that the following conditions are | ||
8 | // met: | ||
9 | // | ||
10 | // * Redistributions of source code must retain the above copyright | ||
11 | // notice, this list of conditions and the following disclaimer. | ||
12 | // * Redistributions in binary form must reproduce the above | ||
13 | // copyright notice, this list of conditions and the following disclaimer | ||
14 | // in the documentation and/or other materials provided with the | ||
15 | // distribution. | ||
16 | // * Neither the name of Google Inc. nor the names of its | ||
17 | // contributors may be used to endorse or promote products derived from | ||
18 | // this software without specific prior written permission. | ||
19 | // | ||
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | |||
32 | package proto | ||
33 | |||
34 | // Functions for writing the text protocol buffer format. | ||
35 | |||
36 | import ( | ||
37 | "bufio" | ||
38 | "bytes" | ||
39 | "encoding" | ||
40 | "errors" | ||
41 | "fmt" | ||
42 | "io" | ||
43 | "log" | ||
44 | "math" | ||
45 | "reflect" | ||
46 | "sort" | ||
47 | "strings" | ||
48 | ) | ||
49 | |||
50 | var ( | ||
51 | newline = []byte("\n") | ||
52 | spaces = []byte(" ") | ||
53 | endBraceNewline = []byte("}\n") | ||
54 | backslashN = []byte{'\\', 'n'} | ||
55 | backslashR = []byte{'\\', 'r'} | ||
56 | backslashT = []byte{'\\', 't'} | ||
57 | backslashDQ = []byte{'\\', '"'} | ||
58 | backslashBS = []byte{'\\', '\\'} | ||
59 | posInf = []byte("inf") | ||
60 | negInf = []byte("-inf") | ||
61 | nan = []byte("nan") | ||
62 | ) | ||
63 | |||
64 | type writer interface { | ||
65 | io.Writer | ||
66 | WriteByte(byte) error | ||
67 | } | ||
68 | |||
69 | // textWriter is an io.Writer that tracks its indentation level. | ||
70 | type textWriter struct { | ||
71 | ind int | ||
72 | complete bool // if the current position is a complete line | ||
73 | compact bool // whether to write out as a one-liner | ||
74 | w writer | ||
75 | } | ||
76 | |||
77 | func (w *textWriter) WriteString(s string) (n int, err error) { | ||
78 | if !strings.Contains(s, "\n") { | ||
79 | if !w.compact && w.complete { | ||
80 | w.writeIndent() | ||
81 | } | ||
82 | w.complete = false | ||
83 | return io.WriteString(w.w, s) | ||
84 | } | ||
85 | // WriteString is typically called without newlines, so this | ||
86 | // codepath and its copy are rare. We copy to avoid | ||
87 | // duplicating all of Write's logic here. | ||
88 | return w.Write([]byte(s)) | ||
89 | } | ||
90 | |||
91 | func (w *textWriter) Write(p []byte) (n int, err error) { | ||
92 | newlines := bytes.Count(p, newline) | ||
93 | if newlines == 0 { | ||
94 | if !w.compact && w.complete { | ||
95 | w.writeIndent() | ||
96 | } | ||
97 | n, err = w.w.Write(p) | ||
98 | w.complete = false | ||
99 | return n, err | ||
100 | } | ||
101 | |||
102 | frags := bytes.SplitN(p, newline, newlines+1) | ||
103 | if w.compact { | ||
104 | for i, frag := range frags { | ||
105 | if i > 0 { | ||
106 | if err := w.w.WriteByte(' '); err != nil { | ||
107 | return n, err | ||
108 | } | ||
109 | n++ | ||
110 | } | ||
111 | nn, err := w.w.Write(frag) | ||
112 | n += nn | ||
113 | if err != nil { | ||
114 | return n, err | ||
115 | } | ||
116 | } | ||
117 | return n, nil | ||
118 | } | ||
119 | |||
120 | for i, frag := range frags { | ||
121 | if w.complete { | ||
122 | w.writeIndent() | ||
123 | } | ||
124 | nn, err := w.w.Write(frag) | ||
125 | n += nn | ||
126 | if err != nil { | ||
127 | return n, err | ||
128 | } | ||
129 | if i+1 < len(frags) { | ||
130 | if err := w.w.WriteByte('\n'); err != nil { | ||
131 | return n, err | ||
132 | } | ||
133 | n++ | ||
134 | } | ||
135 | } | ||
136 | w.complete = len(frags[len(frags)-1]) == 0 | ||
137 | return n, nil | ||
138 | } | ||
139 | |||
140 | func (w *textWriter) WriteByte(c byte) error { | ||
141 | if w.compact && c == '\n' { | ||
142 | c = ' ' | ||
143 | } | ||
144 | if !w.compact && w.complete { | ||
145 | w.writeIndent() | ||
146 | } | ||
147 | err := w.w.WriteByte(c) | ||
148 | w.complete = c == '\n' | ||
149 | return err | ||
150 | } | ||
151 | |||
152 | func (w *textWriter) indent() { w.ind++ } | ||
153 | |||
154 | func (w *textWriter) unindent() { | ||
155 | if w.ind == 0 { | ||
156 | log.Print("proto: textWriter unindented too far") | ||
157 | return | ||
158 | } | ||
159 | w.ind-- | ||
160 | } | ||
161 | |||
162 | func writeName(w *textWriter, props *Properties) error { | ||
163 | if _, err := w.WriteString(props.OrigName); err != nil { | ||
164 | return err | ||
165 | } | ||
166 | if props.Wire != "group" { | ||
167 | return w.WriteByte(':') | ||
168 | } | ||
169 | return nil | ||
170 | } | ||
171 | |||
172 | func requiresQuotes(u string) bool { | ||
173 | // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. | ||
174 | for _, ch := range u { | ||
175 | switch { | ||
176 | case ch == '.' || ch == '/' || ch == '_': | ||
177 | continue | ||
178 | case '0' <= ch && ch <= '9': | ||
179 | continue | ||
180 | case 'A' <= ch && ch <= 'Z': | ||
181 | continue | ||
182 | case 'a' <= ch && ch <= 'z': | ||
183 | continue | ||
184 | default: | ||
185 | return true | ||
186 | } | ||
187 | } | ||
188 | return false | ||
189 | } | ||
190 | |||
191 | // isAny reports whether sv is a google.protobuf.Any message | ||
192 | func isAny(sv reflect.Value) bool { | ||
193 | type wkt interface { | ||
194 | XXX_WellKnownType() string | ||
195 | } | ||
196 | t, ok := sv.Addr().Interface().(wkt) | ||
197 | return ok && t.XXX_WellKnownType() == "Any" | ||
198 | } | ||
199 | |||
200 | // writeProto3Any writes an expanded google.protobuf.Any message. | ||
201 | // | ||
202 | // It returns (false, nil) if sv value can't be unmarshaled (e.g. because | ||
203 | // required messages are not linked in). | ||
204 | // | ||
205 | // It returns (true, error) when sv was written in expanded format or an error | ||
206 | // was encountered. | ||
207 | func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { | ||
208 | turl := sv.FieldByName("TypeUrl") | ||
209 | val := sv.FieldByName("Value") | ||
210 | if !turl.IsValid() || !val.IsValid() { | ||
211 | return true, errors.New("proto: invalid google.protobuf.Any message") | ||
212 | } | ||
213 | |||
214 | b, ok := val.Interface().([]byte) | ||
215 | if !ok { | ||
216 | return true, errors.New("proto: invalid google.protobuf.Any message") | ||
217 | } | ||
218 | |||
219 | parts := strings.Split(turl.String(), "/") | ||
220 | mt := MessageType(parts[len(parts)-1]) | ||
221 | if mt == nil { | ||
222 | return false, nil | ||
223 | } | ||
224 | m := reflect.New(mt.Elem()) | ||
225 | if err := Unmarshal(b, m.Interface().(Message)); err != nil { | ||
226 | return false, nil | ||
227 | } | ||
228 | w.Write([]byte("[")) | ||
229 | u := turl.String() | ||
230 | if requiresQuotes(u) { | ||
231 | writeString(w, u) | ||
232 | } else { | ||
233 | w.Write([]byte(u)) | ||
234 | } | ||
235 | if w.compact { | ||
236 | w.Write([]byte("]:<")) | ||
237 | } else { | ||
238 | w.Write([]byte("]: <\n")) | ||
239 | w.ind++ | ||
240 | } | ||
241 | if err := tm.writeStruct(w, m.Elem()); err != nil { | ||
242 | return true, err | ||
243 | } | ||
244 | if w.compact { | ||
245 | w.Write([]byte("> ")) | ||
246 | } else { | ||
247 | w.ind-- | ||
248 | w.Write([]byte(">\n")) | ||
249 | } | ||
250 | return true, nil | ||
251 | } | ||
252 | |||
253 | func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { | ||
254 | if tm.ExpandAny && isAny(sv) { | ||
255 | if canExpand, err := tm.writeProto3Any(w, sv); canExpand { | ||
256 | return err | ||
257 | } | ||
258 | } | ||
259 | st := sv.Type() | ||
260 | sprops := GetProperties(st) | ||
261 | for i := 0; i < sv.NumField(); i++ { | ||
262 | fv := sv.Field(i) | ||
263 | props := sprops.Prop[i] | ||
264 | name := st.Field(i).Name | ||
265 | |||
266 | if name == "XXX_NoUnkeyedLiteral" { | ||
267 | continue | ||
268 | } | ||
269 | |||
270 | if strings.HasPrefix(name, "XXX_") { | ||
271 | // There are two XXX_ fields: | ||
272 | // XXX_unrecognized []byte | ||
273 | // XXX_extensions map[int32]proto.Extension | ||
274 | // The first is handled here; | ||
275 | // the second is handled at the bottom of this function. | ||
276 | if name == "XXX_unrecognized" && !fv.IsNil() { | ||
277 | if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { | ||
278 | return err | ||
279 | } | ||
280 | } | ||
281 | continue | ||
282 | } | ||
283 | if fv.Kind() == reflect.Ptr && fv.IsNil() { | ||
284 | // Field not filled in. This could be an optional field or | ||
285 | // a required field that wasn't filled in. Either way, there | ||
286 | // isn't anything we can show for it. | ||
287 | continue | ||
288 | } | ||
289 | if fv.Kind() == reflect.Slice && fv.IsNil() { | ||
290 | // Repeated field that is empty, or a bytes field that is unused. | ||
291 | continue | ||
292 | } | ||
293 | |||
294 | if props.Repeated && fv.Kind() == reflect.Slice { | ||
295 | // Repeated field. | ||
296 | for j := 0; j < fv.Len(); j++ { | ||
297 | if err := writeName(w, props); err != nil { | ||
298 | return err | ||
299 | } | ||
300 | if !w.compact { | ||
301 | if err := w.WriteByte(' '); err != nil { | ||
302 | return err | ||
303 | } | ||
304 | } | ||
305 | v := fv.Index(j) | ||
306 | if v.Kind() == reflect.Ptr && v.IsNil() { | ||
307 | // A nil message in a repeated field is not valid, | ||
308 | // but we can handle that more gracefully than panicking. | ||
309 | if _, err := w.Write([]byte("<nil>\n")); err != nil { | ||
310 | return err | ||
311 | } | ||
312 | continue | ||
313 | } | ||
314 | if err := tm.writeAny(w, v, props); err != nil { | ||
315 | return err | ||
316 | } | ||
317 | if err := w.WriteByte('\n'); err != nil { | ||
318 | return err | ||
319 | } | ||
320 | } | ||
321 | continue | ||
322 | } | ||
323 | if fv.Kind() == reflect.Map { | ||
324 | // Map fields are rendered as a repeated struct with key/value fields. | ||
325 | keys := fv.MapKeys() | ||
326 | sort.Sort(mapKeys(keys)) | ||
327 | for _, key := range keys { | ||
328 | val := fv.MapIndex(key) | ||
329 | if err := writeName(w, props); err != nil { | ||
330 | return err | ||
331 | } | ||
332 | if !w.compact { | ||
333 | if err := w.WriteByte(' '); err != nil { | ||
334 | return err | ||
335 | } | ||
336 | } | ||
337 | // open struct | ||
338 | if err := w.WriteByte('<'); err != nil { | ||
339 | return err | ||
340 | } | ||
341 | if !w.compact { | ||
342 | if err := w.WriteByte('\n'); err != nil { | ||
343 | return err | ||
344 | } | ||
345 | } | ||
346 | w.indent() | ||
347 | // key | ||
348 | if _, err := w.WriteString("key:"); err != nil { | ||
349 | return err | ||
350 | } | ||
351 | if !w.compact { | ||
352 | if err := w.WriteByte(' '); err != nil { | ||
353 | return err | ||
354 | } | ||
355 | } | ||
356 | if err := tm.writeAny(w, key, props.MapKeyProp); err != nil { | ||
357 | return err | ||
358 | } | ||
359 | if err := w.WriteByte('\n'); err != nil { | ||
360 | return err | ||
361 | } | ||
362 | // nil values aren't legal, but we can avoid panicking because of them. | ||
363 | if val.Kind() != reflect.Ptr || !val.IsNil() { | ||
364 | // value | ||
365 | if _, err := w.WriteString("value:"); err != nil { | ||
366 | return err | ||
367 | } | ||
368 | if !w.compact { | ||
369 | if err := w.WriteByte(' '); err != nil { | ||
370 | return err | ||
371 | } | ||
372 | } | ||
373 | if err := tm.writeAny(w, val, props.MapValProp); err != nil { | ||
374 | return err | ||
375 | } | ||
376 | if err := w.WriteByte('\n'); err != nil { | ||
377 | return err | ||
378 | } | ||
379 | } | ||
380 | // close struct | ||
381 | w.unindent() | ||
382 | if err := w.WriteByte('>'); err != nil { | ||
383 | return err | ||
384 | } | ||
385 | if err := w.WriteByte('\n'); err != nil { | ||
386 | return err | ||
387 | } | ||
388 | } | ||
389 | continue | ||
390 | } | ||
391 | if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { | ||
392 | // empty bytes field | ||
393 | continue | ||
394 | } | ||
395 | if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { | ||
396 | // proto3 non-repeated scalar field; skip if zero value | ||
397 | if isProto3Zero(fv) { | ||
398 | continue | ||
399 | } | ||
400 | } | ||
401 | |||
402 | if fv.Kind() == reflect.Interface { | ||
403 | // Check if it is a oneof. | ||
404 | if st.Field(i).Tag.Get("protobuf_oneof") != "" { | ||
405 | // fv is nil, or holds a pointer to generated struct. | ||
406 | // That generated struct has exactly one field, | ||
407 | // which has a protobuf struct tag. | ||
408 | if fv.IsNil() { | ||
409 | continue | ||
410 | } | ||
411 | inner := fv.Elem().Elem() // interface -> *T -> T | ||
412 | tag := inner.Type().Field(0).Tag.Get("protobuf") | ||
413 | props = new(Properties) // Overwrite the outer props var, but not its pointee. | ||
414 | props.Parse(tag) | ||
415 | // Write the value in the oneof, not the oneof itself. | ||
416 | fv = inner.Field(0) | ||
417 | |||
418 | // Special case to cope with malformed messages gracefully: | ||
419 | // If the value in the oneof is a nil pointer, don't panic | ||
420 | // in writeAny. | ||
421 | if fv.Kind() == reflect.Ptr && fv.IsNil() { | ||
422 | // Use errors.New so writeAny won't render quotes. | ||
423 | msg := errors.New("/* nil */") | ||
424 | fv = reflect.ValueOf(&msg).Elem() | ||
425 | } | ||
426 | } | ||
427 | } | ||
428 | |||
429 | if err := writeName(w, props); err != nil { | ||
430 | return err | ||
431 | } | ||
432 | if !w.compact { | ||
433 | if err := w.WriteByte(' '); err != nil { | ||
434 | return err | ||
435 | } | ||
436 | } | ||
437 | |||
438 | // Enums have a String method, so writeAny will work fine. | ||
439 | if err := tm.writeAny(w, fv, props); err != nil { | ||
440 | return err | ||
441 | } | ||
442 | |||
443 | if err := w.WriteByte('\n'); err != nil { | ||
444 | return err | ||
445 | } | ||
446 | } | ||
447 | |||
448 | // Extensions (the XXX_extensions field). | ||
449 | pv := sv.Addr() | ||
450 | if _, err := extendable(pv.Interface()); err == nil { | ||
451 | if err := tm.writeExtensions(w, pv); err != nil { | ||
452 | return err | ||
453 | } | ||
454 | } | ||
455 | |||
456 | return nil | ||
457 | } | ||
458 | |||
459 | // writeAny writes an arbitrary field. | ||
460 | func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { | ||
461 | v = reflect.Indirect(v) | ||
462 | |||
463 | // Floats have special cases. | ||
464 | if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { | ||
465 | x := v.Float() | ||
466 | var b []byte | ||
467 | switch { | ||
468 | case math.IsInf(x, 1): | ||
469 | b = posInf | ||
470 | case math.IsInf(x, -1): | ||
471 | b = negInf | ||
472 | case math.IsNaN(x): | ||
473 | b = nan | ||
474 | } | ||
475 | if b != nil { | ||
476 | _, err := w.Write(b) | ||
477 | return err | ||
478 | } | ||
479 | // Other values are handled below. | ||
480 | } | ||
481 | |||
482 | // We don't attempt to serialise every possible value type; only those | ||
483 | // that can occur in protocol buffers. | ||
484 | switch v.Kind() { | ||
485 | case reflect.Slice: | ||
486 | // Should only be a []byte; repeated fields are handled in writeStruct. | ||
487 | if err := writeString(w, string(v.Bytes())); err != nil { | ||
488 | return err | ||
489 | } | ||
490 | case reflect.String: | ||
491 | if err := writeString(w, v.String()); err != nil { | ||
492 | return err | ||
493 | } | ||
494 | case reflect.Struct: | ||
495 | // Required/optional group/message. | ||
496 | var bra, ket byte = '<', '>' | ||
497 | if props != nil && props.Wire == "group" { | ||
498 | bra, ket = '{', '}' | ||
499 | } | ||
500 | if err := w.WriteByte(bra); err != nil { | ||
501 | return err | ||
502 | } | ||
503 | if !w.compact { | ||
504 | if err := w.WriteByte('\n'); err != nil { | ||
505 | return err | ||
506 | } | ||
507 | } | ||
508 | w.indent() | ||
509 | if v.CanAddr() { | ||
510 | // Calling v.Interface on a struct causes the reflect package to | ||
511 | // copy the entire struct. This is racy with the new Marshaler | ||
512 | // since we atomically update the XXX_sizecache. | ||
513 | // | ||
514 | // Thus, we retrieve a pointer to the struct if possible to avoid | ||
515 | // a race since v.Interface on the pointer doesn't copy the struct. | ||
516 | // | ||
517 | // If v is not addressable, then we are not worried about a race | ||
518 | // since it implies that the binary Marshaler cannot possibly be | ||
519 | // mutating this value. | ||
520 | v = v.Addr() | ||
521 | } | ||
522 | if etm, ok := v.Interface().(encoding.TextMarshaler); ok { | ||
523 | text, err := etm.MarshalText() | ||
524 | if err != nil { | ||
525 | return err | ||
526 | } | ||
527 | if _, err = w.Write(text); err != nil { | ||
528 | return err | ||
529 | } | ||
530 | } else { | ||
531 | if v.Kind() == reflect.Ptr { | ||
532 | v = v.Elem() | ||
533 | } | ||
534 | if err := tm.writeStruct(w, v); err != nil { | ||
535 | return err | ||
536 | } | ||
537 | } | ||
538 | w.unindent() | ||
539 | if err := w.WriteByte(ket); err != nil { | ||
540 | return err | ||
541 | } | ||
542 | default: | ||
543 | _, err := fmt.Fprint(w, v.Interface()) | ||
544 | return err | ||
545 | } | ||
546 | return nil | ||
547 | } | ||
548 | |||
549 | // equivalent to C's isprint. | ||
550 | func isprint(c byte) bool { | ||
551 | return c >= 0x20 && c < 0x7f | ||
552 | } | ||
553 | |||
554 | // writeString writes a string in the protocol buffer text format. | ||
555 | // It is similar to strconv.Quote except we don't use Go escape sequences, | ||
556 | // we treat the string as a byte sequence, and we use octal escapes. | ||
557 | // These differences are to maintain interoperability with the other | ||
558 | // languages' implementations of the text format. | ||
559 | func writeString(w *textWriter, s string) error { | ||
560 | // use WriteByte here to get any needed indent | ||
561 | if err := w.WriteByte('"'); err != nil { | ||
562 | return err | ||
563 | } | ||
564 | // Loop over the bytes, not the runes. | ||
565 | for i := 0; i < len(s); i++ { | ||
566 | var err error | ||
567 | // Divergence from C++: we don't escape apostrophes. | ||
568 | // There's no need to escape them, and the C++ parser | ||
569 | // copes with a naked apostrophe. | ||
570 | switch c := s[i]; c { | ||
571 | case '\n': | ||
572 | _, err = w.w.Write(backslashN) | ||
573 | case '\r': | ||
574 | _, err = w.w.Write(backslashR) | ||
575 | case '\t': | ||
576 | _, err = w.w.Write(backslashT) | ||
577 | case '"': | ||
578 | _, err = w.w.Write(backslashDQ) | ||
579 | case '\\': | ||
580 | _, err = w.w.Write(backslashBS) | ||
581 | default: | ||
582 | if isprint(c) { | ||
583 | err = w.w.WriteByte(c) | ||
584 | } else { | ||
585 | _, err = fmt.Fprintf(w.w, "\\%03o", c) | ||
586 | } | ||
587 | } | ||
588 | if err != nil { | ||
589 | return err | ||
590 | } | ||
591 | } | ||
592 | return w.WriteByte('"') | ||
593 | } | ||
594 | |||
595 | func writeUnknownStruct(w *textWriter, data []byte) (err error) { | ||
596 | if !w.compact { | ||
597 | if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { | ||
598 | return err | ||
599 | } | ||
600 | } | ||
601 | b := NewBuffer(data) | ||
602 | for b.index < len(b.buf) { | ||
603 | x, err := b.DecodeVarint() | ||
604 | if err != nil { | ||
605 | _, err := fmt.Fprintf(w, "/* %v */\n", err) | ||
606 | return err | ||
607 | } | ||
608 | wire, tag := x&7, x>>3 | ||
609 | if wire == WireEndGroup { | ||
610 | w.unindent() | ||
611 | if _, err := w.Write(endBraceNewline); err != nil { | ||
612 | return err | ||
613 | } | ||
614 | continue | ||
615 | } | ||
616 | if _, err := fmt.Fprint(w, tag); err != nil { | ||
617 | return err | ||
618 | } | ||
619 | if wire != WireStartGroup { | ||
620 | if err := w.WriteByte(':'); err != nil { | ||
621 | return err | ||
622 | } | ||
623 | } | ||
624 | if !w.compact || wire == WireStartGroup { | ||
625 | if err := w.WriteByte(' '); err != nil { | ||
626 | return err | ||
627 | } | ||
628 | } | ||
629 | switch wire { | ||
630 | case WireBytes: | ||
631 | buf, e := b.DecodeRawBytes(false) | ||
632 | if e == nil { | ||
633 | _, err = fmt.Fprintf(w, "%q", buf) | ||
634 | } else { | ||
635 | _, err = fmt.Fprintf(w, "/* %v */", e) | ||
636 | } | ||
637 | case WireFixed32: | ||
638 | x, err = b.DecodeFixed32() | ||
639 | err = writeUnknownInt(w, x, err) | ||
640 | case WireFixed64: | ||
641 | x, err = b.DecodeFixed64() | ||
642 | err = writeUnknownInt(w, x, err) | ||
643 | case WireStartGroup: | ||
644 | err = w.WriteByte('{') | ||
645 | w.indent() | ||
646 | case WireVarint: | ||
647 | x, err = b.DecodeVarint() | ||
648 | err = writeUnknownInt(w, x, err) | ||
649 | default: | ||
650 | _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) | ||
651 | } | ||
652 | if err != nil { | ||
653 | return err | ||
654 | } | ||
655 | if err = w.WriteByte('\n'); err != nil { | ||
656 | return err | ||
657 | } | ||
658 | } | ||
659 | return nil | ||
660 | } | ||
661 | |||
662 | func writeUnknownInt(w *textWriter, x uint64, err error) error { | ||
663 | if err == nil { | ||
664 | _, err = fmt.Fprint(w, x) | ||
665 | } else { | ||
666 | _, err = fmt.Fprintf(w, "/* %v */", err) | ||
667 | } | ||
668 | return err | ||
669 | } | ||
670 | |||
671 | type int32Slice []int32 | ||
672 | |||
673 | func (s int32Slice) Len() int { return len(s) } | ||
674 | func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } | ||
675 | func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
676 | |||
677 | // writeExtensions writes all the extensions in pv. | ||
678 | // pv is assumed to be a pointer to a protocol message struct that is extendable. | ||
679 | func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { | ||
680 | emap := extensionMaps[pv.Type().Elem()] | ||
681 | ep, _ := extendable(pv.Interface()) | ||
682 | |||
683 | // Order the extensions by ID. | ||
684 | // This isn't strictly necessary, but it will give us | ||
685 | // canonical output, which will also make testing easier. | ||
686 | m, mu := ep.extensionsRead() | ||
687 | if m == nil { | ||
688 | return nil | ||
689 | } | ||
690 | mu.Lock() | ||
691 | ids := make([]int32, 0, len(m)) | ||
692 | for id := range m { | ||
693 | ids = append(ids, id) | ||
694 | } | ||
695 | sort.Sort(int32Slice(ids)) | ||
696 | mu.Unlock() | ||
697 | |||
698 | for _, extNum := range ids { | ||
699 | ext := m[extNum] | ||
700 | var desc *ExtensionDesc | ||
701 | if emap != nil { | ||
702 | desc = emap[extNum] | ||
703 | } | ||
704 | if desc == nil { | ||
705 | // Unknown extension. | ||
706 | if err := writeUnknownStruct(w, ext.enc); err != nil { | ||
707 | return err | ||
708 | } | ||
709 | continue | ||
710 | } | ||
711 | |||
712 | pb, err := GetExtension(ep, desc) | ||
713 | if err != nil { | ||
714 | return fmt.Errorf("failed getting extension: %v", err) | ||
715 | } | ||
716 | |||
717 | // Repeated extensions will appear as a slice. | ||
718 | if !desc.repeated() { | ||
719 | if err := tm.writeExtension(w, desc.Name, pb); err != nil { | ||
720 | return err | ||
721 | } | ||
722 | } else { | ||
723 | v := reflect.ValueOf(pb) | ||
724 | for i := 0; i < v.Len(); i++ { | ||
725 | if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { | ||
726 | return err | ||
727 | } | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | return nil | ||
732 | } | ||
733 | |||
734 | func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { | ||
735 | if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { | ||
736 | return err | ||
737 | } | ||
738 | if !w.compact { | ||
739 | if err := w.WriteByte(' '); err != nil { | ||
740 | return err | ||
741 | } | ||
742 | } | ||
743 | if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { | ||
744 | return err | ||
745 | } | ||
746 | if err := w.WriteByte('\n'); err != nil { | ||
747 | return err | ||
748 | } | ||
749 | return nil | ||
750 | } | ||
751 | |||
752 | func (w *textWriter) writeIndent() { | ||
753 | if !w.complete { | ||
754 | return | ||
755 | } | ||
756 | remain := w.ind * 2 | ||
757 | for remain > 0 { | ||
758 | n := remain | ||
759 | if n > len(spaces) { | ||
760 | n = len(spaces) | ||
761 | } | ||
762 | w.w.Write(spaces[:n]) | ||
763 | remain -= n | ||
764 | } | ||
765 | w.complete = false | ||
766 | } | ||
767 | |||
768 | // TextMarshaler is a configurable text format marshaler. | ||
769 | type TextMarshaler struct { | ||
770 | Compact bool // use compact text format (one line). | ||
771 | ExpandAny bool // expand google.protobuf.Any messages of known types | ||
772 | } | ||
773 | |||
774 | // Marshal writes a given protocol buffer in text format. | ||
775 | // The only errors returned are from w. | ||
776 | func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { | ||
777 | val := reflect.ValueOf(pb) | ||
778 | if pb == nil || val.IsNil() { | ||
779 | w.Write([]byte("<nil>")) | ||
780 | return nil | ||
781 | } | ||
782 | var bw *bufio.Writer | ||
783 | ww, ok := w.(writer) | ||
784 | if !ok { | ||
785 | bw = bufio.NewWriter(w) | ||
786 | ww = bw | ||
787 | } | ||
788 | aw := &textWriter{ | ||
789 | w: ww, | ||
790 | complete: true, | ||
791 | compact: tm.Compact, | ||
792 | } | ||
793 | |||
794 | if etm, ok := pb.(encoding.TextMarshaler); ok { | ||
795 | text, err := etm.MarshalText() | ||
796 | if err != nil { | ||
797 | return err | ||
798 | } | ||
799 | if _, err = aw.Write(text); err != nil { | ||
800 | return err | ||
801 | } | ||
802 | if bw != nil { | ||
803 | return bw.Flush() | ||
804 | } | ||
805 | return nil | ||
806 | } | ||
807 | // Dereference the received pointer so we don't have outer < and >. | ||
808 | v := reflect.Indirect(val) | ||
809 | if err := tm.writeStruct(aw, v); err != nil { | ||
810 | return err | ||
811 | } | ||
812 | if bw != nil { | ||
813 | return bw.Flush() | ||
814 | } | ||
815 | return nil | ||
816 | } | ||
817 | |||
818 | // Text is the same as Marshal, but returns the string directly. | ||
819 | func (tm *TextMarshaler) Text(pb Message) string { | ||
820 | var buf bytes.Buffer | ||
821 | tm.Marshal(&buf, pb) | ||
822 | return buf.String() | ||
823 | } | ||
824 | |||
825 | var ( | ||
826 | defaultTextMarshaler = TextMarshaler{} | ||
827 | compactTextMarshaler = TextMarshaler{Compact: true} | ||
828 | ) | ||
829 | |||
830 | // TODO: consider removing some of the Marshal functions below. | ||
831 | |||
832 | // MarshalText writes a given protocol buffer in text format. | ||
833 | // The only errors returned are from w. | ||
834 | func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } | ||
835 | |||
836 | // MarshalTextString is the same as MarshalText, but returns the string directly. | ||
837 | func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } | ||
838 | |||
839 | // CompactText writes a given protocol buffer in compact text format (one line). | ||
840 | func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } | ||
841 | |||
842 | // CompactTextString is the same as CompactText, but returns the string directly. | ||
843 | func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } | ||